Codeforces Round #428 (Div. 2) B.Game of the Rows(贪心+炒鸡多坑的模拟)

97 篇文章 0 订阅
11 篇文章 0 订阅

B. Game of the Rows
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Daenerys Targaryen has an army consisting of k groups of soldiers, the i-th group contains ai soldiers. She wants to bring her army to the other side of the sea to get the Iron Throne. She has recently bought an airplane to carry her army through the sea. The airplane has nrows, each of them has 8 seats. We call two seats neighbor, if they are in the same row and in seats {1, 2}{3, 4}{4, 5}{5, 6} or {7, 8}.

A row in the airplane

Daenerys Targaryen wants to place her army in the plane so that there are no two soldiers from different groups sitting on neighboring seats.

Your task is to determine if there is a possible arranging of her army in the airplane such that the condition above is satisfied.

Input

The first line contains two integers n and k (1 ≤ n ≤ 100001 ≤ k ≤ 100) — the number of rows and the number of groups of soldiers, respectively.

The second line contains k integers a1, a2, a3, ..., ak (1 ≤ ai ≤ 10000), where ai denotes the number of soldiers in the i-th group.

It is guaranteed that a1 + a2 + ... + ak ≤ 8·n.

Output

If we can place the soldiers in the airplane print "YES" (without quotes). Otherwise print "NO" (without quotes).

You can choose the case (lower or upper) for each letter arbitrary.

Examples
input
2 2
5 8
output
YES
input
1 2
7 1
output
NO
input
1 2
4 4
output
YES
input
1 4
2 2 1 2
output
YES
Note

In the first sample, Daenerys can place the soldiers like in the figure below:

In the second sample, there is no way to place the soldiers in the plane since the second group soldier will always have a seat neighboring to someone from the first group.

In the third example Daenerys can place the first group on seats (1, 2, 7, 8), and the second group an all the remaining seats.

In the fourth example she can place the first two groups on seats (1, 2) and (7, 8), the third group on seats (3), and the fourth group on seats (5, 6).


题解:

刚刚终于ac了这题!!!昨天晚上打cf到了0点没撑住就睡了。。第一次打cf就只a了一题。。。我为何那么水,话说这题昨天wa了一晚上,可以先说一下,这题坑炒鸡多的

题意:

有很多组人上飞机,但是不同的组不愿意相邻,问是否能满足他们的需求坐得下

思路:

我的模拟代码很长,不太好解释,详细在代码里面有。。。写得有点挫,这题的坑点在于一排8个位置中4,5的位置是不能相邻的,我是把这些座位种类分成了两组,一组是两遍座位,也就是1278的位置,还有是中间座位3456的位置,这两位置分开讨论,然后对于每一组的人数根据奇偶也分开讨论,对于上一个的数字的奇数偶数也分开讨论。。还有就是从大到小排一下序,因为我贪心思路是先放中间的位置,因为中间的位置不灵活,两边的位置是可以放2个人的,而中间的位置放2个人的时候也会出现一系列问题。。反正这题贼麻烦

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<string>
#include<stdio.h>
#include<queue>
#include<stack>
#include<map>
#include<deque>
#define M (t[k].l+t[k].r)/2
#define lson k*2
#define rson k*2+1
#define ll long long
#define INF 100861111;
using namespace std;
int a[10005];
int main()
{
    int i,j,k,n,tag=1,d1,d2,x,f=0,flag=0;
    scanf("%d%d",&n,&k);
    for(i=0;i<k;i++)
    {
        scanf("%d",&a[i]);
    }
    sort(a,a+k);//从大到小排序。。我这里因为当时迫切想知道对不对直接懒得写cmp函数了,倒过来一样的
    d1=d2=4*n;//d1表示两边剩余位置数量,d2表示中间剩余位置数量
    int t=4*n;
    for(i=k-1;i>=0;i--)
    {
        x=a[i];
        if(x%2)//如果是奇数
        {
            if(f)//如果可以找到单人座位
            {
                f--;//f是剩余的可以做单人的位置数量
                x--;
                if(d2>=x)//先放中间的位置,如果中间位置有空
                {
                    if(d2%4==0)//看是否是4,5位置,不是直接减
                        d2-=x;
                    else//是4,5号位置
                    {
                        if(d2>=(x+2))//后面有2个额外的空位
                        {
                            d2-=(x+2);
                            f++;//因为放了偶数个以后下一次这里最多只能有单人位置了
                        }
                        else
                        {
                                d2-=x;//没有就有多少减多少
                            f++;
                            d1-=2;
                        }
                    }
                }
                else//中间位置数量不足
                {
                    if(d2!=0)//有多少减多少
                    {
                        if(d2%4==0)
                        {
                            x-=d2;
                            d2=0;
                        }
                        else
                        {
                            x-=(d2-2);
                            d2=0;
                            f++;
                        }
                        }
                    d1-=x;
                }
            }
            else//找不到单人座位
            {
                if(d2!=0)
                    flag=1;//这个flag很重要,标记了下一次中间位置是否可以放双人位,想想,如果当前是单人位,那么下一次相邻就可以放双人位
                if(d2>=x)//先放中间位置
                {
                    d2-=x;
                    d2--;
                }
                else
                {
                    x-=d2;
                    d2=0;
                    d1-=(x+1);
                }
            }
        }
        else//如果是偶数,这里可以直接复制上面的奇数个减去单人位的偶数情况,可以写成一个函数就简洁多了,下面的和上面的差不多就不解释了
        {
            if(d2>=x)
                {
                    if(d2%4==0)
                        d2-=x;
                    else
                    {
                        if(flag)//只有这里和上面不同,如果上次放的是中间的单人位,可以放偶数个人
                        {
                            flag=0;
                                d2-=x;
                        }
                        else if(d2>=(x+2))//否则就要覆盖掉2个位置,把2个位置变成一个单人位
                        {
                            d2-=(x+2);
                            f++;
                        }
                        else//中间位置不足,有多少减多少
                        {
                            d2-=x;
                            f++;
                            d1-=2;
                        }
                    }
                }
                else//中间不足,和上面差不多
                {
                    if(d2!=0)
                    {
                        if(d2%4==0)
                        {
                            x-=d2;
                            d2=0;
                        }
                        else
                        {
                            x-=(d2-2);
                            d2=0;
                            f++;
                        }
                    }
                    d1-=x;
                }
        }
        if(d1<0)//这里也很重要,因为输入的数据里面有个坑,比如2 7     2 2 2 2 2 2 2这组数据,可以将一个组拆成两个单人位就可以放得下
        {
            if(f+d1>=0)
            {
                f+=d1;
                d1=0;
            }
        }
        if(d1<0||d2<0)//如果出现负数情况就判断失败
        {
            tag=0;
            break;
        }
    }
    if(tag)
        printf("YES\n");
    else
        printf("NO\n");
    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值