Codeforces 839B Game of the Rows (贪心)

题目链接

CF 839B

题目大意

k 组人,第i组有 ai 个人。飞机上有 n <script type="math/tex" id="MathJax-Element-196">n</script>排座位,每排座位如下图:
这里写图片描述
问是否存在一种就座方案,使得不存在不同组的人坐在相邻的位置。

分析

这是Round #428 (Div.2)的B题,当时比赛的时候是通过的,赛后被Hack掉了(新增数据见注释)。。。自己想的情况还是不够全面。
显然这是一道贪心题。

  • 首先我们尽可能的让同一组的4个人去坐四人座
  • 然后尽可能让同一组的2个人去坐两人座
  • 此时考虑剩余的4人座,有以下几种就座情况:
    {AAA_} {AA_B} {A__B}
    前两种情况可以归结为,安排同一组的两个人坐4人座,还能有一个单人座给任一组的人坐,第三种情况为安排1个人座4人座,也可以安排另一个组的人来坐。

  • 因此,我们先尽量安排2个人坐剩余的4人座,每坐一组相当于多出来单人座

  • 如果还有剩余的4人座,就安排1个人去4人座,每坐一组也多出个单人座
  • 让剩余的人尽可能去坐多出来的单人座
  • 如果还有人剩余,也有2人座剩余,安排1组的1个人坐二人座

  • 进行完这些操作后,如果还有人剩余则不存在方案,如果没人剩余则存在方案。

代码

#include <bits/stdc++.h>
using namespace std;
const double pi=4*atan(1.0);
int a[10010];
int main()
{
    int n,k,i,num_2,num_4,temp;
    bool flag;
    scanf("%d%d",&n,&k);
    for (i=1;i<=k;i++)
        scanf("%d",&a[i]);
    num_2=2*n;num_4=n;
    for (i=1;i<=k;i++)
    {
        /**先尽可能让同一组的4个人坐4人座*/
        while (a[i]>=4&&num_4)
        {
            a[i]-=4;
            num_4--;
        }

    }
    for (i=1;i<=k;i++)
    {
        /**接着尽可能让同一组的2个人坐2人座*/
        while (a[i]>=2&&num_2)
        {
            num_2--;
            a[i]-=2;
        }
    }
    for (i=1;i<=k;i++)
    {
        while (a[i]==3&&num_4)
        {
            num_4--;
            a[i]-=3;
        }
    }
    /**temp表示4人座做两个同一组的人,留出单人座的数量*/
    temp=0;
    for (i=1;i<=k;i++)
    {
        while (a[i]==2&&num_4)
        {
            num_4--;
            temp++;
            a[i]-=2;
        }
    }
    /*安排某一组的人坐4人座,多出一个万能单人座*/
    for (i=1;i<=k;i++)
    {
        while (a[i]==1&&num_4)
        {
            a[i]--;
            num_4--;
            temp++;
        }
    }
    /*安排人座万能单人座*/
    for (i=1;i<=k;i++)
    {
        while (a[i]&&temp)
        {
            temp--;
            a[i]--;
        }
    }
    /*如果还有2人座剩余,就安排某一组的1个人去坐*/
    for (i=1;i<=k;i++)
    {
        while (a[i]==1&&num_2)
        {
            a[i]--;
            num_2--;
        }
    }

    flag=true;
    for (i=1;i<=k;i++)
        if (a[i])
        {
            flag=false;
            break;
        }
    if (flag) printf("YES\n");
        else printf("NO\n");
    return 0;
}
/*
1 4
1 1 2 2

2 7
2 2 2 2 2 2 2

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值