Codeforces Round #428 (Div. 2) B. Game of the Rows

来源:互联网 发布:js获取标签属性 编辑:程序博客网 时间:2024/05/22 19:05

题目链接

http://codeforces.com/contest/839/problem/B

题目大意

给你k组士兵, 每组有ai人, 你有n排座位, 每排座位如下图所示
座位
即{1, 2}, {3, 4}, {4, 5}, {5, 6}, {7, 8}这些座位相邻
问你士兵能否都坐下且保证不同组的士兵不坐在相邻座位上
(题目保证人数<座位数)

思路

这题我们可以用贪心做, 一下把3~6座简称4座, 1~2 和 7~8简称2座

贪心策略

1.如果一组人能把4座的座位坐满, 那就尽量用4座的座位给他们坐,4座的没了就用2座的
2.这样处理完了之后每只队伍人数就只剩下1, 2, 3这三种情况了
然后我们再安排3个人的队伍入座, 同样优先选择4座的, 然后2座的
3.安排2个人的队伍入座, 这时我们优先选择2座的再选择4座的
4.安排一个人的队伍入座, 这时就不用考虑先座哪个了, 能坐下就好了

证明

  1. 对于4座和2座的比较, 首先一排中2座有两个, 所以它能坐下的人数和四座无区别, 但是4座的无法坐下两只两个人的队伍, 所以在第一步2座相比4座珍贵, 所以优先选择4座的
  2. 同上
  3. 这里2座和4座的优先级其实差不多orz
  4. 没了

细节

  1. 两个人的队伍坐到四座之后其实还能空出一个座位给一个人坐
  2. 三个人的队伍可以拆成2 + 1, 也就是两个人坐在2座, 一个人去4座
  3. 两个人的队伍可以拆成1 + 1, 然后占两个4座

代码

#include<bits/stdc++.h>using namespace std;int a[105];int cnt[5];int main(){    int n, k;    scanf("%d%d", &n, &k);    for(int i=1; i<=k; ++i)        scanf("%d", a+i);    sort(a+1, a+k+1);    bool flag = true;    int top = k, c2 = 2*n, c4 = n, c1 = 0;    for(int i=k; i>=1; --i)    {        if(a[i] < 4) ++cnt[a[i]];        else if(c4 == 0)        {            c2 -= a[i]/2;            ++cnt[a[i]%2];        }        else if(c4 - a[i]/4 >= 0)        {            c4 -= a[i]/4;            ++cnt[a[i]%4];        }        else if(c4 - a[i]/4 < 0)        {            a[i] -= c4 * 4;            c4 = 0;            c2 -= a[i]/2;            ++cnt[a[i]%2];        }    }    if(c2 < 0 && c4 == 0) puts("NO");    else     {        for(int i=0; i<cnt[3]; ++i)        {            if(c4 - 1 >= 0) --c4;            else c2 -= 2;        }        for(int i=0; i<cnt[2]; ++i)        {            if(c2 - 1 >= 0) --c2;            else            {                if(c4 - 1 >= 0)                {                    --c4;                    ++c1;                }                else c1 -= 2;            }        }        int sum = 0;        if(c1 > 0) sum += c1;        if(c2 > 0) sum += c2;        if(c4 > 0) sum += c4 * 2;        if(c1 < cnt[1] && c2 <= 0 && c4 <= 0)puts("NO");        else if(sum >= cnt[1] && c2 >= 0 && c4 >= 0 && c1 >= 0)            puts("YES");        else puts("NO");    }    return 0;}

膜拜

其实很多情况可以合并, 这样可以缩很多行, 少很多if, 再用一些奇妙(guai)的语法规则, 就可以变成下面这样

#include<iostream>int i,n,k,a,s,j;main(){for(std::cin>>n>>k;i<k;i++)std::cin>>a,a%2?a++,j++:0,s+=a;std::cout<<(s>8*n||s==8*n&&k==4*n&&j<n?"NO":"YES");}

Orz

阅读全文
0 0