思路:题目描述的大致意思就是:给定n张牌,每张牌分成正面和反面,正面和反面都涂有颜色(颜色用数字代替),每次可以翻动一张牌,使得一张牌的另一面朝上,这样问需要最少翻动多少次才能使得不少于n/2张牌的颜色相同,如果没有答案的话,则输出-1.
这道题的做法有两种:(1)记录每张牌的正面和反面,并记录它们出现的次数,当某个颜色的在正面出现次数和在反面的出现次数>=n/2时,那么就找到一种满足情况,遍历所有的颜色,找出最小的一种就行了。(使用STL中的map记录)
(2)使用结构体数组,记录每张牌的正面和反面的颜色,并记录他们处于正面还是反面,然后再使用sort对颜色大小排序,之后遍历所有颜色,当某种颜色出现次数>=n/2时,这样就找到满足情况的颜色,依次类推,找到最小的情况即可。
特殊注意:有些牌的正面颜色和反面颜色相同,那么只需要记录其正面即可。还有当某个颜色处于正面的次数>=n/2时,直接输出0即可。
分别给出两种思路的代码:
第一种:
#include <iostream> #include <cstdio> #include <cstring> #include <map> using namespace std; struct node { int l,r; } ; map<int,node>hash; int s[200009]; int main() { int n; scanf("%d",&n); int i,x,y,k=0; for(i=0; i<n; i++) { scanf("%d%d",&x,&y); if(x!=y) { hash[x].l++; hash[y].r++; s[k++]=x; s[k++]=y; } else hash[x].l++,s[k++]=x; } int l=-1; for(i=0; i<k; i++) if(hash[s[i]].l+hash[s[i]].r>=(n+1)/2) { if(hash[s[i]].l>=(n+1)/2) { l=0; break; } else { if(l==-1) l=(n+1)/2-hash[s[i]].l; else l=min(l,(n+1)/2-hash[s[i]].l); } } printf("%d\n",l); return 0; }
第二种:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct node { int x; int m; } s[201000]; bool cmp(node a,node b) { return a.x<b.x; } int main() { int n; while(scanf("%d",&n)!=-1) { int k=0; int a,b; for(int i=0;i<n;i++) { scanf("%d%d",&a,&b); if(a!=b) { s[k].x=a; s[k++].m=0; s[k].x=b; s[k++].m=1; } else { s[k].x=a; s[k++].m=0; } } sort(s,s+k,cmp); //for(int i=0;i<k;i++) // printf("%d %d\n",s[i].x,s[i].m); int l=-1,ans=0; int i,j=0; for(i=0;i<k;i=j) { if(s[i].m) ans=0; else ans=1; for(j=i+1;j<k&&s[i].x==s[j].x;j++) if(s[j].m==0) ans++; if(j-i>=(n+1)/2) { if(ans>=(n+1)/2) { l=0;i=k;j=k;break; } else { if(l==-1) l=(n+1)/2-ans; else l=min(l,(n+1)/2-ans); } } } printf("%d\n",l); } return 0; }
codeforces 204B- Little Elephant and Cards,布布扣,bubuko.com
codeforces 204B- Little Elephant and Cards
原文:http://blog.csdn.net/knight_kaka/article/details/21246765