[蓝桥杯]完美的代价

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

时间限制: 1Sec 内存限制: 128MB 提交: 261 解决: 73

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

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

例如mamad

第一次交换 ad : mamda

第二次交换 md : madma

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

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

第二行是一个字符串,长度为N.只包含小写字母
输出
如果可能,输出最少的交换次数。

否则输出Impossible
样例输入
5

mamad
样例输出
3

解题思路:

(贪心算法)。。嗯,在做这道题之前,我是不会这个算法的。易懂,多练习。

  1. 首先对输入的字符串ch[]拷贝到cch[](用于判断字符串是否可以成为回文字符串)
	cin>>ch;
	for(long long i=0;i<N;i++)
		cch[i]=ch[i];
  1. 对cch[]进行排序,计算每一个字符出现的个数
	for(long long i=0;i<N;i++)
		for(long long j=i+1;j<N;j++)
		{
			if(cch[i]>cch[j])
			{
				char flagch=cch[i];
				cch[i]=cch[j];
				cch[j]=flagch;
			}
		}
  1. 回文字符串中每一种字符串的奇数出现数量,不能大于1。比如abbbcddd中b和d都出现了三次,这个字符串中大于一个的字符数量为奇数,所以不能构成回文。对cch[]进行判断
	for(long long i=0;i<N;i++)
	{
		if(cch[i]==cch[i+1]&&i<N)
			t++;
		else
		{
			if(t%2==1) t1++;
			if(t1>=2) break;
			t=1;
		}
	}
  1. 进一步细分
if(t1>=2)
		cout<<"Impossible";
	else
		/*计算步数*/
  1. 计算步数
		i=0;
		for(j=N-1;j>i;j--)
		{
			for(t=j;t>i;t--)
				if(ch[t]==ch[i])
				{
					sum+=j-t;
					char flagch=ch[t];
					while(t<j)
					{
						ch[t]=ch[t+1];
						t++;
					}
					ch[j]=flagch;
					i++;
					break;
				}
  1. 写到这里提交之后,提示有45%的错误,看了题解之后发现少了这一部分。
    之前的程序中解决了当奇数字符串时候,中心的字符在后半部分的情况,如果中心字符在前半部分,则会出现从后往前查找时无法查到。所以,当出现这种情况的时候,先将这个中心字符向后移一位。最后的结果自然就是刚好到中心位置。(如果程序是从前往后查找,则相反)
	if(t==i&&j!=i)
	{
		j++;
		char c=ch[i];
		ch[i]=ch[i+1];
		ch[i+1]=c;
		sum++;
	}

以下是完整代码(注意数组越界)

#include<iostream>
#include<string>
using namespace std;

int main()
{
	long long N;
	cin>>N;
	char ch[8010],cch[8010];
	cin>>ch;
	long long t=1,t1=0,sum=0;
	for(long long i=0;i<N;i++)
		cch[i]=ch[i];
	for(long long i=0;i<N;i++)
		for(long long j=i+1;j<N;j++)
		{
			if(cch[i]>cch[j])
			{
				char flagch=cch[i];
				cch[i]=cch[j];
				cch[j]=flagch;
			}
		}
	for(long long i=0;i<N;i++)
	{
		if(cch[i]==cch[i+1]&&i<N)
			t++;
		else
		{
			if(t%2==1) t1++;
			if(t1>=2) break;
			t=1;
		}
	}
	long long i,j;
	if(t1>=2)
		cout<<"Impossible";
	else
	{
		i=0;
		for(j=N-1;j>i;j--)
		{
			for(t=j;t>i;t--)
				if(ch[t]==ch[i])
				{
					sum+=j-t;
					char flagch=ch[t];
					while(t<j)
					{
						ch[t]=ch[t+1];
						t++;
					}
					ch[j]=flagch;
					i++;
					break;
				}
			if(t==i&&j!=i)
			{
				j++;
				char c=ch[i];
				ch[i]=ch[i+1];
				ch[i+1]=c;
				sum++;
			}
		}
		cout<<sum;
	}
	
	return 0;
}

欢迎大家留言交流代码!

猜你喜欢

转载自blog.csdn.net/DanBo_C/article/details/87895119