贪心算法之Evil Straw Warts Live

 

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值