回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母
输出
如果可能,输出最少的交换次数。
否则输出Impossible
样例输入
5 mamad
样例输出
3
动态规划问题
#include<stdlib.h>
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
char a[n];
scanf("%s",a);
long sum=0;
int flag=0;
/*偶数和奇数循环体在最后的判断上不同,需要分类*/
if(n%2==0)
{
for(int i=0;i<n/2;i++)//考虑前半段
{
if(a[n-1-i]!=a[i])//后半段与之一一对应
{
flag=0;
for(int k=n-2-i;k>i;k--)//在中间寻找目标字符,前段的字母固定,
{
if(a[k]==a[i])
{
char t=a[k];
for(int j=k;j<n-i-1;j++)//移动
{
a[j]=a[j+1];
}
a[n-i-1]=t;
sum+=(n-i-1-k);
flag=1;//表示能找到
break;
}
}
if(flag==0)//靠近后段的字母固定,在中间寻找该字母
{
for(int k=i+1;k<n-1-i;k++)
{
if(a[k]==a[n-1-i])
{
char t=a[k];
for(int j=k-1;j>=i;j--)
{
a[j+1]=a[j];
}
a[i]=t;
sum+=(k-i);
flag=1;
break;
}
}
}
if(flag==0)//表示前端和后端都找不到
{
printf("Impossible\n");
exit(0);
}
}
}
if(a[n/2-1]==a[n/2])
{
flag=1;
}
else
{
flag=0;
}
}
else//考虑奇数
{
for(int i=0;i<n/2;i++)
{
if(a[n-1-i]!=a[i])
{
flag=0;
for(int k=n-2-i;k>i;k--)
{
if(a[k]==a[i]&&k!=i)
{
char t=a[k];
for(int j=k;j<n-i-1;j++)
{
a[j]=a[j+1];
}
a[n-i-1]=t;
sum+=(n-i-1-k);
flag=1;
break;
}
}
if(flag==0)
{
for(int k=i+1;k<n-1-i;k++)
{
if(a[k]==a[n-1-i])
{
char t=a[k];
for(int j=k-1;j>=i;j--)
{
a[j+1]=a[j];
}
a[i]=t;
sum+=(k-i);
flag=1;
break;
}
}
}
if(flag==0)
{
printf("Impossible\n");
exit(0);
}
}
}
}
if(flag==1)
printf("%ld\n",sum);
else
printf("Impossible\n");
return 0;
}