完美的代价 c语言,蓝桥杯基础练习 完美的代价

基础练习 完美的代价

问题:

问题描述

回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。

交换的定义是:交换两个相邻的字符

例如mamad

第一次交换 ad : mamda

第二次交换 md : madma

第三次交换 ma : madam (回文!完美!)

输入格式

第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)

第二行是一个字符串,长度为N.只包含小写字母

输出格式

如果可能,输出最少的交换次数。

否则输出Impossible

样例输入

5

mamad

样例输出

3

需要了解:

这道题的关键字是贪心算法,去百度了一下贪心算法,简单来说就是在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。

在本题中也就是找到能够与之相匹配的字符。然后,进行交换,直至达到目标要求。

题目分析:

首先分析Impossible 的两种情况

n为奇数时,如果已经有一个字符出现的次数为奇数,还找到了一个字符出现的次数为奇数,那么就不能构成回文串。

n为偶数时,只要找到有一个字符出现的次数为奇数,那么就不能构成回文串。

还有一个就是题目所说的最小的交换次数

如果 n 为偶数,那么从第一字符开始,从后往前找第一个和它相同的字符,如果找了,就将找到的字符交换到最后一个位置,在下一次遍历时,就可以不用管刚才已经交换好的那来两个字符,下一次从第二个字符开始,从倒数第二个字符开始遍历,执行和上述相同的操作。

如果 n 为奇数,在字符串的某一个位置找到了那个出现次数为奇数的字符,我们不必将次字符现在就交换到中间位置,而是先计算它到中间位置需要交换的次数,然后累加到 count 中,将剩下的字符都交换到对称后,再交换这个字符即可。

这是因为如果把奇数移动到中间,假设有一对数都在以中间为界限的左边或者都在右边的话,那么交换成回文的时候就一定要经过中间,这就会造成count多增加了一次,这是不必要的,因为可以所有的回文移动完了之后再把这个独立的奇数移动过去,不仅能达到同样的效果还能保证交换次数最少。

例如:

有这么几个数

b d c c f f b

我们不考虑第二个奇数直接交换第三个数,这样只需要1步,但是当你把第二个奇数交换到中间之后就会有如下结果

b c c d f f b

可以了解一下 φ(>ω

代码:

#include

#include

using namespace std;

int main() {

int n;

cin >> n;

string s;

cin >> s;

int end = n - 1;//字符串最后一个字符

int count = 0;//交换次数

int OddNum = 0;//判断是否已经有一个单独的奇个数的字符了

for (int i = 0; i < end; ++i) {//从第一个字符到倒数第二个字符遍历

for (int j = end; j >= i; --j) {//从最后一个开始,到第i个字符,寻找与s[i]相同的字符

if (i == j) {//如果没找到

if (n % 2 == 0 || OddNum == 1) { //不可能的两种情况

cout << "Impossible" << endl;

return 0;

}

OddNum = 1;//找到一个字符出现的次数为奇数

count += n / 2 - i;//将次字符交换到中间位置的次数

}

else if (s[i] == s[j]) {//如果找到了,将s[j]交换到s[end]位置

for (int k = j; k < end; ++k) {

swap(s[k], s[k + 1]);//交换相邻两个位置的字符

++count;

}

--end;//末尾递减

break; //开始从i+1处重复操作

}

}

}

cout << count << endl;

system("pause");

return 0;

}

对于我:

但是在这里我还发现我有一个基础知识点薄弱的地方那就是多个if跟if··· if else 的区别

if (条件){语句}

这种格式中,程序会依次判断条件1和条件2是否成立并根据结果决定是否执行语句1和语句2,也就是说,第一个 if 块和第二个 if 块没有影响(除非在执行第一个 if 块的时候就凶残地 return 了)

而下面这种格式,

if (条件){}

else if(条件){}

f 块和 else if 块本质上是互斥的!也就是说,一旦语句1得到了执行,程序会跳过 else if 块,else if 块中的判断语句以及语句2一定会被跳过;同时语句2的执行也暗含了条件1判断失败和语句1没有执行;当然还有第3个情况,就是条件1和条件2都判断失败,语句1和语句2都没有得到执行。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值