蓝桥杯基础练习VIP-完美的代价
(代价确实有点重哈)
时间限制: 1Sec 内存限制: 128MB 提交: 4015 解决: 1150
题目描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入
第一行是一个整数N,表示接下来的字符串的长度(N < = 8000)
第二行是一个字符串,长度为N.只包含小写字母输出
如果可能,输出最少的交换次数。
否则输出Impossible样例输入复制
5样例输出复制
3
代码如下,注释超级超级详细! 详细讲解题目,点击吧
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
string s;
cin>>s;
int j=n-1;
int cnt=0; //cnt用来统计交换的次数
int flag=0; //flag判断是否已经有一个单独的奇个数的字符了
for(int i=0;i<j;i++)
{ //i从左往右遍历,i从开头开始指向每个字符
for(int k=j;k>=i;k--)
{ //k从右向左遍历,k从结尾开始指向每个字符
if(k==i) //当k=i时,说明一直未找到当i!=k时, s[k]==s[i]
{
if(n%2==0||flag==1) //(1)当n为偶数,并有字符找不到配对的, impossible
// (2)当n为偶数,并出现了第二个字符没有配对,impossible
{
printf("Impossible");
return 0;
}
flag=1; //n为奇数,第一次出现字符没有配对,做个标记
cnt+=n/2-i; // 把该字符交换到中间所用的次数
}
else if(s[k]==s[i]) //找到了相同的字符,并且i!=k,不是同一个字符
{
for(int l=k;l<j;l++) //把s[k]交换到s[j]处
{
//交换两个相邻位置的字符
swap(s[l],s[l+1]); //最后时,l+1=j,所以l<j,无等号
cnt++; //记录交换次数
}
j--; //末尾递减
break; //结束此次k的循环,开头递增i++,重复操作
}
}
}
printf("%d",cnt);
return 0;
}