期望得分: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);
}
View Code

相关文章:

  • 2022-01-24
  • 2021-11-09
  • 2022-02-20
  • 2021-09-23
  • 2021-08-13
  • 2021-11-11
  • 2021-06-26
  • 2021-09-24
猜你喜欢
  • 2021-10-27
  • 2022-01-10
  • 2021-11-13
  • 2022-01-29
  • 2021-10-03
  • 2021-11-05
  • 2021-07-13
相关资源
相似解决方案