[蓝桥杯] 基础练习 完美的代价
Posted 凌星An
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[蓝桥杯] 基础练习 完美的代价相关的知识,希望对你有一定的参考价值。
问题描述
问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)输入格式
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母输出格式
如果可能,输出最少的交换次数。 否则输出Impossible
样例输入
5 mamad
样例输出
3
思路:
① 首先,我们确定一点,该字符串中出现奇数次的字符最多只能有一个,
如果出现一个以上,该字符串注定不是回文串,我们输出Impossible即可
② 现在的情况一定是能够够成回文串的情况
那现在面临的问题是,怎么实现最小交换次数?
我们考虑单个字符
我们从左侧开始遍历,当遍历第i个字符的时候,我们从右侧对称位置往左 侧找对称字符,找到之后进行减缓,一定是这个字符对称所走的最小次数
所有单个字符都做最小步数,那么总体就是走的最小步数
我们上面看到如果没有奇数字符的话,上面的方法是可以得到结果的。
那么如果有奇数字符呢?
如果有奇数字符的话,我们不处理奇数字符;从奇数字符的对称位置往左边处理,即处理不含奇数字符的子串,和上述的处理过程相同。
代码实现
#include<iostream>
using namespace std;
#include<string>
int Fun(string str,char ch)
int count=0;
int n=str.size();
for(int i=0;i<n/2;++i)
if(str[i]==ch)
//如果是奇数字符
//我们需要从右侧 匹配对应的字母,进行移动
int j=i;
for(j=i;j<n-1-i;j++)
if(str[j]==str[n-1-i])
break;
count += j - i;
for (int k = j; k > i; k--)
str[k] = str[k - 1];
str[i] = str[n - i - 1] ;
else
//不是奇数字母
//可以按照正常处理顺序,按照左侧的字母去右侧寻找对称的字母
int j=n-1-i;
for(j=n-1-i;j>=i;--j) //在i的位置必定能够找到
if(str[i]==str[j])
break;
count+=n-1-i-j;
for(int k=j;k<n-1-i;++k)
str[k]=str[k+1];
str[n-1-i]=str[i];
return count;
int main()
int N;
string str;
while(cin>>N>>str)
//一个数组,用来统计字符串中每个字母的个数
int count[26]=0;
for(int i=0;i<str.size();++i)
count[str[i]-'a']++;
int oddcount=0;
char oddch=0;
for(int i=0;i<26;++i)
if(count[i]%2!=0)
oddcount++;
oddch=i+'a';
//如果奇数的字母出现次数大于1,必定不能形成回文串
if(oddcount>1)
cout<<"Impossible"<<endl;
else
cout<<Fun(str,oddch)<<endl;
return 0;
觉得不错,来个赞呗
以上是关于[蓝桥杯] 基础练习 完美的代价的主要内容,如果未能解决你的问题,请参考以下文章