期望得分:100+50+20=170
实际得分:10+50+20=80
1. 纸牌
题目描述
在桌面上放着n张纸牌,每张纸牌有两面,每面都写着一个非负整数。你的邪王真眼可以看到所有牌朝上的一面和朝下的一面写的数字。现在你需要将一些牌翻过来,使得所有牌朝上的一面中,至少有一半(≥n/2)的数字是一样的。请你求出最少需要翻几张牌,或者判断无解。
注意:在翻牌的时候,你不能把牌扔掉,不能偷偷把别的牌放进来,也不能用笔涂改牌上面的数字。
输入格式
第一行包含一个整数n,表示牌的数量;
接下来n行,每行两个非负整数ai, bi,表示每张牌上写的两个数字,ai对应朝上的一面,bi对应朝下的一面。
输出格式
如果有解,则输出一个整数,表示最少的翻牌次数,否则输出Impossible。
样例输入1
3
1 2
2 1
3 4
样例输出1
1
样例解释1
把第一张牌翻过来,那么就有两个2一个3朝上了,2的数量超过了半数。
样例输入2
3
1 2
3 4
5 6
样例输出2
Impossible
样例解释2
所有数字都只有一个,因此相同的数字数超过半数是不可能的。
最多只有四种数的个数会超过n/2,
所有数先排序,然后枚举,当一个数的个数为n/2时,就用这个数来更新答案
注意:如果正反都为同一个数,这个数只能算1个
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 300001 int a[N],b[N],c[N<<1]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } int main() { freopen("card.in","r",stdin); freopen("card.out","w",stdout); int n,cnt=0; read(n); for(int i=1;i<=n;++i) { read(a[i]); c[++cnt]=a[i]; read(b[i]); if(a[i]!=b[i]) c[++cnt]=b[i]; } sort(c+1,c+cnt+1); int ans=n+1,sum=0,m=n+1>>1; for(int i=1;i<=cnt;++i) { if(c[i]==c[i-1]) { ++sum; if(sum==m) { int tot=0; for(int j=1;j<=n;++j) if(a[j]==c[i]) tot++; tot=min(tot,m); ans=min(ans,m-tot); } } else sum=1; } if(ans>n) printf("Impossible"); else printf("%d",ans); }