题目描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入格式
第一行是一个整数N,表示接下来的字符串的长度(N < = 8000)
第二行是一个字符串,长度为N.只包含小写字母
输出格式
如果可能,输出最少的交换次数。
否则输出Impossible
样例输入
5 mamad
样例输出
3
思路
记录字符串,从边缘开始制作回文串。从左边开始定位,记录当前元素,再从右边开始找到相同元素,移动到与左边对应的位置,这样边缘的元素就对应完成,接着查找下一个元素,将所有移动次数记录下来然后输出
遇到单独字符时可以用公式计算移动次数,计算从此处到中心处的移动次数(因为相同字符是向右交换的,所以单独的字符会被挤到左边去,直接减去就行),如果此时字符串是偶数个或者有多个单独的字符,就输出Impossible
#include<stdio.h>
#include<string.h>
int swapNum(char* c, int left, int right) {//逐渐交换到最后
for (int i = left;i < right;i++) {
int k = c[i];
c[i] = c[i + 1];
c[i + 1] = k;
}
return right - left;//返回移动次数
}
int main() {
int n;
char c[8100];
scanf("%d\n", &n);
scanf("%s", c);
int changeNum = 0;//交换次数
int onlyNum = 0;//单独元素数量
int i, j;
int k = n;
for (i = 0;i < k - 1;i++) {//从左向右找寻
for (j = k - 1;j >= i;j--) {//右边的相同元素
if (i == j) {//只有这一个元素
onlyNum++;
if (onlyNum > 1 || n % 2 == 0) {//多个单独元素或字符长度是偶数
printf("Impossible\n");
return 0;
}
changeNum += n / 2 - i;//将此元素移动到中间位置的次数
break;
}
if (c[i] == c[j]) {//找到相同元素
changeNum += swapNum(c, j, k - 1);//移动到对应位置,得到次数
k--;//边缘向内收缩
break;
}
}
}
printf("%d\n", changeNum);
return 0;
}

被折叠的 条评论
为什么被折叠?



