贪心算法之Evil Straw Warts Live

来源:互联网 发布:脂肪坏处 知乎 编辑:程序博客网 时间:2024/06/06 12:43

 

Evil Straw Warts Live

Description

A palindrome is astring of symbols that is equal to itself when reversed. Given an input string,not necessarily a palindrome, compute the number of swaps necessary totransform the string into a palindrome. By swap we mean reversing the order oftwo adjacent symbols. For example, the string "mamad" may betransformed into the palindrome "madam" with 3 swaps: 
swap "ad" to yield "mamda" 
swap "md" to yield "madma" 
swap "ma" to yield "madam" 

Input

The first line ofinput gives n, the number of test cases. For each test case, one line of inputfollows, containing a string of up to 8000 lowercase letters.

Output

Output consists ofone line per test case. This line will contain the number of swaps, or"Impossible" if it is not possible to transform the input to apalindrome. 

Sample Input

3

mamad

asflkj

aabb

Sample Output

3

Impossible

2

题目意思:给出一个字符串,如果经由交换能使其成为一个回文,则输出最小交换步骤;如果经过交换不能使其成为回文,则输出Impossible。注意,这里的交换指的是相邻的两个字符之间的交换。
解题思路:
本题应用贪心算法解题。首先判断所给的字符串能不能形成回文。如果能形成回文,则开始计算步骤。计算步骤时,得考虑到是否有落单的情况。本题的贪心算法体现在:从后往前找找到第一个与第一个字符相同的字符然后后移
具体的程序为:
// 1854.cpp : 定义控制台应用程序的入口点。
 
#include<iostream>
using namespace std;
 
#define maxchar 8005 //字符串长度
 
char value[maxchar]; //存储字符串
int key[26]; //由于字符串都是由小写字母构成,key[i]表示'a'+i出现的次数,如果为奇数,则落单
int marked[maxchar]; //用来标记哪个字符落单
 
void Init(); //初始化
bool Judge(); //判断能否形成回文
void Solve(); //解决步骤
int main()
{
      int n;
      cin>>n;
      while(n>0)
      {
            Init();
            cin>>value;
            bool hw=Judge();
            if(!hw)
            {
                  cout<<"Impossible"<<endl;
            }
            else
            {
                  Solve();
            }
            n-=1;
      }
      return 0;
}
void Init()
{
      for(int i=0;i<maxchar;i++)
      {
            value[i]='\0';
            marked[i]=0;
      }
      for(int i=0;i<26;i++)
      {
            key[i]=0;
      }
}
bool Judge()
{
      for(int i=0;value[i]!='\0';i++)
      {
            key[value[i]-'a']+=1; //这里用相对关系解决了字符出现次数关系
      }
      int hui=0;
      for(int i=0;i<26;i++)
      {
            if(key[i]%2==1)
            {
                  hui+=1;
                  if(hui>=2)
                  {
                        //如果落单情况达到了2个就说明源字符串不可能形成回文
                        return false;
                  }
            }
      }
      return true;
}
void Solve()
{
      int count=0;
      int length;
      for(int i=0;value[i]!='\0';i++)
      {
            //字符串长度
            length=i;
      }
      int end=length;
      for(int i=0;i<=length/2;i++)
      {
            for(int j=end;j>i;j--)
            {
                  if(value[j]==value[i])
                  {
                        char c=value[j];
                        for(int k=j+1;k<=end;k++)
                               value[k-1]=value[k];
                        value[end]=c;
                        marked[i]=1;
                        count+=end-j;
                        end-=1;
                        break;
                  }
            }
      }
      if(length%2==0)
      {
            //考虑落单情况
            char c;
            for(int i=0;i<26;i++)
            {
                  if(key[i]%2==1)
                  {
                        c='a'+i;
                        break;
                  }
            }
            for(int i=0;i<=length;i++)
            {
                  if((value[i]==c)&&(marked[i]==0))
                  {
                        if(i<=length/2)
                               count+=length/2-i;
                        else
                               count+=i-length/2;
                        break;
                  }
            }
      }
      cout<<count<<endl;
}
 
 
分析:
本题的时间复杂度为:O(n2)。最坏情况为:aabbcc……每次都得从最后找到很靠前的位置。
0 0
原创粉丝点击