第一部分:题目
问题描述 回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!) 输入格式 第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母 输出格式 如果可能,输出最少的交换次数。
否则输出Impossible 样例输入 5
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;
}