[蓝桥杯]试题 基础练习 完美的代价

在这里插入图片描述
在这里插入图片描述

参考:

https://blog.csdn.net/liuchuo/article/details/51990430

分析:过程见代码注释部分。其中有两个注意点:
1.impossible的情况:如果有一个字符出现的次数是奇数次数,而且n是偶数,那么不可能构成回文
如果n是奇数,但是已经有一个字符出现的次数是奇数次数了,那么如果又有一个字符是奇数次数,就不可能构成回文。
2.如果n是奇数,计算中间那个字符交换的次数的时候,不需要模拟把这个数移动到中间去,因为移动到中间的话假设有一对数都在左边或者都在右边,那么交换成回文的时候就要经过中间,就会每次把cnt多加了1,而这个1是没有必要的,因为可以所有的回文移动完了之后再把这个独立的奇数移动过去,才能保证交换次数最少。
————————————————
版权声明:本文为CSDN博主「柳婼」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/liuchuo/article/details/51990430

代码:

#include<iostream>
#include<string>
#include<vector>

using namespace std;

int main()
{
	string str = "";
	int n;
	cin>>n;
	cin>>str;
	int res = 0;
	int left = 0,right = n - 1;
	bool flag = false;
 	while(left < right)
 	{
 		for(int k = right; k >= left; k--)
 		{
 			if(k == left)//str[left]只有奇数个 
 			{
 				if( n % 2 == 0 || flag == true)
				{//n位偶数时不能有奇数个的字符,n为奇数时不能有两个奇数个的字符 
				 	cout<<"Impossible";
					 return 0;	
				} 
				flag = true;
				res += n/2 - left; //把str[left]移动到最中间,但先在先不移 
				left++; //只让left右移,right不动
 			}
 			else if(str[k] == str[left])
			{//找到了 
			 	for(int t = k;  t < right; t++)
			 	{//交换 
			 		swap(str[t],str[t+1]);
			 		res++;
			 	}
			 	left++;
			 	right--;
			 	break;
			} 
 		}
 	} 
 	cout<<res;
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值