蓝桥杯 基础练习basic 19 完美的代价(C++详细思路图解)
完美的代价
题目
问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入格式
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母
输出格式
如果可能,输出最少的交换次数。
否则输出Impossible
样例输入
5
mamad
样例输出
3
思路:
- 首先题目要求同样得到回文串的结果,只用最少的交换次数。因此采用贪心算法,也就是每一步只考虑达到当前最有情况的解法,即从头开始遍历字符串,直到一半长度,挨个匹配回文;
- 回文串分两种,偶数长度的回文串字符都是偶数倍出现,奇数长度的回文串则有一个单独的字符串;
- 根据第二点可知,奇数长度的回文串需要特殊处理处于正中间的那个字符。
思路图解:

代码如下:
#include <iostream>
#include <string>
using namespace std;
string str;
int steps, len, mid = -1, p;
void myswap(int i, int j)
{
char temp = str[i];
if (mid != -1) // 因为跳过了中间位置字母,所以移动位置要对应的往后平移1个位置
j++;
for (int x = i; x < j; x++)
str[x] = str[x + 1];
str[j] = temp;
steps += j - i;
}
int main()
{
cin >> len;
cin >> str;
for (int i = 0; i < len / 2; i++)
{
if (mid != -1)
p = 1;
if (str[i] == str[len - 1 - i + p])
continue;
else
{
int flag = 1; // 假设有字符没找到对应回文
for (int j = len - 2 - i + p; j >= i + 1; j--) // 反向找匹配的字母,以减少步数
if (str[j] == str[i])
{
myswap(j, len - 1 - i);
flag = 0;
break;
}
if (flag)
if (len & 1) // 若是奇数字符串
{
mid = i; // 记下中间字母的位置,最后来移动
continue;
}
else // 偶数字符串且有单个字符,直接打印结果返回
{
cout << "Impossible" << endl;
return 0;
}
}
}
if (mid != -1) // 对于奇数字符串,加上最后移动中间字符的步数
steps += len / 2 - mid;
cout << steps << endl;
return 0;
}

浙公网安备 33010602011771号