完美的代价(贪心算法)

贪心算法:所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。

思路:从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加算法停止。如果贪婪算法正确工作,那么找到的第一个解通常是最优的。

应用:
蓝桥杯--完美的代价

思路:

1.首先判断IMPOSSIBLE的情况
主要分为两种情况:出现2个及以上的奇数个数 & 出现一个奇数但是字符串长度为偶数

2.字符与字符的交换,可以看作是字符的移动。那么相同的字符,为了求得最少的步骤,我们要保证他们的移动方向是一致的,否则比如一个往右移动4位,另一个往左移动2位,其实就是往右移动了两位。
所以我们从字符串的第一位开始,从右往左遍历,看是否有和它相同的字符。如果找到了,下一次就不用管他们了,遍历的end-1;下一次为字符串第二位寻找,从倒数第二位开始遍历。
(这一步应该是贪心思想的应用,遍历的时候找到相同的字符,换就完事儿了!)

3.假如只有一个出现次数为奇数的字符且字符串长度也为奇数,我们要在最后一步才将他移动到字符串的最中央。试想如果一开始就将它移动到字符串中央,则在他之后其它字符的移动都要加一步,步数变多。所以找到了这个数,直接将cnt加上其所在位置与中间位置的差距即可。

// 以下是代码,感谢网上诸位大佬的优秀思路借鉴!

#include <iostream>
#include <string>
#include<cstring>
#include<iostream>
using namespace std;
int main(){
	int n;
	string a;
	while(cin>>n){
		cin>>a;
		int cnt = 0,flag = 0,f2=0,l=n-1;       //用于判断字符串中出现次数为奇数的字母的个数
		//f2是不知道如何打破两个循环而加的奇奇怪怪的东西...
		for(int i = 0;i<l;i++){
			for(int j = l;j>=i;j--){
				if(i==j){
					if(n%2==0 || flag==1){         //不可能条件:出现2个及以上的奇数个数&一个奇数但是字符串长度为偶数
						cout<<"Impossible"<<endl;
						f2 = 1;
						break;
					}
					cnt += n / 2 - i;    //将次字符交换到中间位置的次数
					flag=1;
				}
				else if(a[i]==a[j]){
					for (int k = j; k < l; k++){    //交换相邻两个位置的字符 
						swap(a[k], a[k+1]);
						cnt++;
					}
					l--;
					break;
				}
			}
			if(f2) break;
		}
		if(f2==0) cout<<cnt<<endl;
	}
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值