CodeForces 356 C.Compartments(贪心)

Description

一桌人数超过两个大家才不会觉得无聊,给出每桌人数,问是否存在一种换座方案使得所有人都不会感到无聊,如果存在输出最少交换次数

Input

第一行一整数 n 表示桌子个数,之后输入n个整数 ai 表示每个桌子的人数 (1n106,0ai4)

Output

如果存在方案使得所有人都不感到无聊则输出最少交换次数,否则输出 1

Sample Input

5
1 2 2 4 3

Sample Output

2

Solution

主要是处理一人桌和两人桌,设其数量分别为 a,b

1.ab ,显然首先用一人桌去把两人桌的变合法,剩下的那些一人桌的三三组合(这样移动两次就可以解决三个人,否则每次移动至多解决一个人),最后剩下的一人桌有 0,1,2 三种情况。此时如果一人桌的数量不超过三人桌的数量,那么把一人桌移动到三人桌即可;否则如果有两个一人桌的话,此时三人桌至多一个,无法解决这两个一人桌,此时需要四人桌来解决,即四人桌出一个人和这两个人组成一个三人桌;否则如果有一个一人桌的话,此时没有三人桌,只能四人桌来解决,且至少需要两个四人桌一桌出一人来和这个落单的组成三人桌;以上条件都不满足则无解

2.a<b ,先用一人桌去解决一部分二人桌,然后二人桌三三组合(这样移动两次就可以解决三个二人桌,比从四人桌移动一人来解决一个二人桌更优),之后剩下的二人桌有 0,1,2 三种情况。如果只剩下一个二人桌,如果有四人桌,那么来一个人即可解决这个二人桌,如果没有三人桌则至少需要两个三人桌来放这两个人,否则无解;如果剩下两个二人桌,只需把这两个二人桌凑成一个四人桌即可

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=10;
int n,m[5]; 
int main()
{
    while(~scanf("%d",&n))
    {
        memset(m,0,sizeof(m));
        while(n--)
        {
            int a;
            scanf("%d",&a);
            m[a]++;
        }
        int ans=0;
        if(m[1]>=m[2])
        {
            m[1]-=m[2],m[3]+=m[2],ans+=m[2],m[2]=0;
            m[3]+=m[1]/3,ans+=m[1]/3*2,m[1]%=3; 
            if(m[1]<=m[3])ans+=m[1];
            else if(m[4]&&m[1]==2)ans+=2;
            else if(m[4]>=2&&m[1]==1)ans+=2;
            else ans=-1; 
        }
        else 
        {
            m[2]-=m[1],m[3]+=m[1],ans+=m[1],m[1]=0;
            m[3]+=m[2]/3*2,ans+=m[2]/3*2,m[2]%=3;
            if(m[2]==1)
            {
                if(m[4])ans++;
                else if(m[3]>=2)ans+=2;
                else ans=-1; 
            }
            else if(m[2]==2)ans+=2;
        }
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值