题目描述
小卓同学一直苦于单身,这天他终于鼓起勇气给自己心仪的女生买了一串珍珠项链(项链首尾相连), 当他拿到项链之后发现每个珍珠的颜色不一致(假定只有黄色和白色两种),黄白分布是任意的, 现在他能进行两种操作
1.选取一个珍珠换成自己喜欢的颜色
2.交换项链上两个珍珠的位置;
请问,小卓同学最少操作几次才能够使项链中的颜色交替分布
注:如果永远不能达到小卓同学想要的情况,输出: What a pity!
输入
多组数据
第一行输入n表示珍珠项链的长度 ( 3< =n<=100 000);
第二行输入长度为n的字符串, ‘w’表示白色珍珠,’y’表示为黄色珍珠;
输出
最少的操作次数
样例输入
4
wyyw
3
wyw
6
wwwwww
样例输出
1
What a pity!
3
反思:
比赛的时候没有静下来好好想这道题。只想出了奇数次不成立以及有比较最终字符串的思路。
耗费了大量的时间一直在纠结替换后的判断与如何找到最优解的算法。(这种算法赛后魏仲华通过位运算两两比较也实现了)
回来路上与学长交流后才意识到算法其实很简单。。最终的字符串只有wywy..与ywyw..两种情况
所以只需要找到原字符串到最终字符串变化次数最少的即可。
注:
如何找到最少变化次数?统计w和y位置不对的次数,然后比如在wywy..开头的情况下w6个位置不对 y8个位置不对,那么6个w就完全可以和6个y交换 然后剩下两个y只能选择替换。
所以wywy开头最终变化次数最少为8次 然后再统计在ywyw..开头的情况下 w和y位置不对的次数 找到其中大的那个数即为最少变化次数。
然后wywy... ywyw...两种情况下最少变化次数进行比较 取少的那个即可。
注:
要先在奇数次输入的时候直接输出不进入for循环,否则会出现时间超限的情况。
注:
回来后提交了几次发现WA,结果是用gets输入的问题。虽然用getschar+gets输入没有任何问题
但是可能是因为后台数据 输入的时候 是以4 wyyw 3 www这样在一行进行输入测试的 后台数据没有换行 导致了WA的产生 理亏以后长记性。
代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> int bi(int a,int b) { if(a>b) return a; else return b; } int main() { char a[100051]; int x; int num1,num2; int sum1,sum2; int i; while(scanf("%d",&x)!=EOF) { //getchar(); num1=0,num2=0,sum1=0,sum2=0; //gets(a); scanf("%s",a); if(x%2==1) { printf("What a pity!\n"); } else { for(i=0; i<x; i++) { if(i&1) { if(a[i]!='y') num1++;//统计wywy的情况 if(a[i]!='w') num2++;//统计ywyw的情况 } else { if(a[i]!='w') sum1++;//统计wywy的情况 if(a[i]!='y') sum2++;//统计ywyw的情况 } } if(bi(num1,sum1)>=bi(num2,sum2)) printf("%d\n",bi(num2,sum2)); else printf("%d\n",bi(num1,sum1)); } memset(a,0,sizeof(a)); } return 0; }
华神位运算简化算法代码:
#include <cstdio> #include <cstring> #include <stdlib.h> char s[1000000+20]; int main(){ int n; while(scanf("%d",&n)!=EOF){ scanf("%s",s); int len=strlen(s); if(len%2)printf("What a pity!\n"); else{ int a1=0,a2=0,a3=0,a4=0; for(int i=0;i<n;i+=2){ if(s[i]!='w')a1++; else if(s[i]!='y')a3++; if(s[i+1]!='y')a2++; else if(s[i+1]!='w')a4++; } if(a1>a2){ a1=a1^a2; a2=a1^a2; a1=a1^a2; } if(a3>a4){ a3=a3^a4; a4=a3^a4; a3=a3^a4; } printf("%d\n",a4<a2?a4:a2); } } return 0; }