cf839B Game of the rows

来源:互联网 发布:python f.close 编辑:程序博客网 时间:2024/06/06 00:32

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


题意大概是这样的,一帮人选座位,要求不同组的不能坐在一起。每一行的座位构成都是这样的:
这里写图片描述
那么显然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 10003int 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

原创粉丝点击