cf839B Game of the rows

本文介绍了一种关于座位分配的贪心算法问题。通过将座位分为4人座和2人座,采用特定策略来分配不同组成员的座位,确保满足不同组成员不相邻的要求。最后通过比较剩余座位和需求来判断是否可行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

非常有趣的一道贪心题。考试期间我是毫无思路,然后今天看作者的题解,哇,真玄学。下面我大概就把作者的题解思路说一下,然后誊写一遍作者的代码


题意大概是这样的,一帮人选座位,要求不同组的不能坐在一起。每一行的座位构成都是这样的:
这里写图片描述
那么显然12 34 45 56 78是邻位。现在给你各组的人数,问能不能满足条件。
好,首先为了粉碎一些天真的想法,我们先举几个蛇皮走位:
1行,2个组,每组4个,方法是这样的:
这里写图片描述
又如,1行4个组,是2 2 2 1,方法:
这里写图片描述


那么作者本人是怎么想的呢?
首先我们将座椅分为两种,一种是4人座,一种是2人座。一共有n排,就先将n排分为n个4人座与2n个2人座。

好,那么假设某一组有k个人。我们优先让他们坐在4人座上,如果没有空余的4人座,就让他们去坐2人座。为什么这样排?因为4人座没有两人座灵活,如果某一组有3个人,那么分在一个4人座、2个2人座是等价的;而如果两个组人数分别为为2,2,分两个两人座是允许的,但没办法放四人座;如果两个组人数分别为1,1,1个4人座与2个2人座也是等价的。所以我们发现,4人座安排上没有两人座方便,所以我们优先四人座。

因此我们的第一步就是遍历让k-4,如果没有两人座就-2。当然,这个过程如果4人座和2人座都满了,那直接超载,别多想。而遍历的终止时机,则是k<=2.现在我们剩下的人只有两种情况:1个人成1组,2个人成1组。

对于两人组的处置,我们优先放2人座。因为如果放到4人座上,就会使得4人座只能放一个人。如果2人座满了,就将4人座拆成一个两人座和一个单人座。实在不行先将两个人拆成两个单人,这样,我们消灭了所有的2人,只剩下一堆的单人成组和一堆座。一个四人座可以充当两个单人座,所以最后的判断就是比较单人剩余数量与(2*4人座数量+2人座数量+单人座数量),比较一下就可以了。

总结一下这个结果是如何得出的。

  • 将每个组的人优先分到4人座上,不够的再分到两人座上,直到剩余1个或2个人
  • 将每个2人组优先分到2人座上,否则将4人座拆为1双1单,否则拆成两个单人
  • 比较最后剩余的可座的座位数与单人的剩余量。

那么代码就呼之欲出了:

#include <bits/stdc++.h>
using namespace std;
#define maxn 10003
int twose,fouse,onese;
int cou[4];
int main(){
    int n,k;
    cin>>n>>k;
    twose=n<<1,fouse=n;
    for(int i=0;i<k;++i){
        int p;cin>>p;
        while(p>=3){//步骤1
            if(fouse>0)
                p-=4,--fouse;
            else if(twose>0)
                p-=2,--twose;
            else{
                cout<<"NO"<<endl;
                return 0;
            }
        }
        if(p>0) cou[p]++;
    }
    while(cou[2]){//步骤2
        if(twose>0)
            --cou[2],--twose;
        else if(fouse>0)
            --cou[2],--fouse,++onese;
        else
            --cou[2],cou[1]+=2;
    }
    if(cou[1]<=onese+twose+2*fouse) cout<<"YES"<<endl;//步骤3
    else cout<<"NO"<<endl;
    return 0;
}

贪心好难啊qwq

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值