第一部分:题目
问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入格式
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母
第二行是一个字符串,长度为N.只包含小写字母
输出格式
如果可能,输出最少的交换次数。
否则输出Impossible
否则输出Impossible
样例输入
5
mamad
mamad
样例输出
3
第二部分:我的思路
1,能否变成回文串:记录每个小写字母的个数,只要奇数的个数不超过1就可以。
2,最少交换次数:贪心:从两端同时开始,不一样的时候需要找到最近的替换:两边的都可以替换,只要交换次数最小也就是最近。
第三部分:代码
#include<iostream> #include<stdio.h> using namespace std; int main() { int len; cin>>len; getchar();//接收cin的回车符 char s[8001]; int sum[27]={0};//用来记录26个小写字母的个数 gets(s); for(int i=0;i<len;i++) { sum[s[i]-'a'+1]++; } int t=0; //字母个数为奇数的总数超过1就不可能变成回文串。 for(int i=1;i<27;i++) { if(sum[i]%2!=0) { t++; } if(t>1) { break; } } if(t>1) { cout<<"Impossible"<<endl; } else { int count=0; int i,j; //从两端同时开始,不一样时用离左或右最近的替换:一个一个交换过来。 for(i=0,j=len-1;i<j;i++,j--) { if(s[i]!=s[j]) { int min=10000; int index; int flag=0; //可以替换左边的 for(int l=i+1;l<j;l++) { if(s[l]==s[j]) { if(min>l-i) { min=l-i; index=l; break; } } } //可以替换右边的 for(int l=j-1;l>i;l--) { if(s[l]==s[i]) { if(min>j-l) { min=j-l; index=l; flag=1; break; } } } count+=min; if(flag) { int t=s[index]; for(int k=index;k<j;k++) { s[k]=s[k+1]; } s[j]=t; } else { int t=s[index]; for(int k=index;k>i;k--) { s[k]=s[k-1]; } s[i]=t; } } } cout<<count<<endl; } return 0; }