codeforces #428 Div.2 B. Game of the Rows 贪心、思维

不是水题…写起来巨烦,写的时候思路断了就很不好连起来。

原题链接:
codeforces 839B

大意:
一群人坐飞机。给出飞机的排数 n ,一排 8 座和 k 个 group 。 要求不同 group 的人不能座位相邻。
如图。{1,2},{3,4},{4,5},{5,6},{7,8} 是相邻的。

这里写图片描述

给出几个有代表性的样例:

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

这里写图片描述样例一

思路:
麻烦的是中间 {5,6} 相邻的情况,否则处理一下奇数即可。
首先容易想到贪心地去坐。
大于 4 人的,把 4 人的坐了,做到最大化利用。然后考虑特殊的情况 比如 aa bb0c dd
这种重叠情况通过代码实现比较烦,这里学习到一种很清晰的解法。

把 group 用优先队列处理就很方便

① 先把 4 人座坐掉。
② 再坐 2 人座,此时考虑的时候 4 人座当 2 人座,意义相同。
③ 那么 剩下来的人都是孤单的,为 1。 这些人能坐 剩下来的所有座位。可以发现剩下来的所有座位都是“2 人座(4人中的两人或是2人座)”,因为上面是按照偶数来减掉的。这样就是最优做法。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back
//#define LOCAL
inline void read(int &x){
    x=0;char p=getchar();
    while(!(p<='9'&&p>='0'))p=getchar();
    while(p<='9'&&p>='0')x*=10,x+=p-48,p=getchar();
}
int main() {
    int n,k;
    read(n);read(k);
    priority_queue<int> q;
    while(!q.empty()) q.pop();
    for(int i=0;i<k;i++){
        int x;
        read(x);
        q.push(x);
    }
    int x4=0;
    while(x4<n && !q.empty()){
        if(q.top()<4) break;
        int t=q.top();
        q.pop();
        if(t/4+x4<=n){
            x4+=t/4;
            t%=4;
            if(t) q.push(t);
        }else {
            t-=4*(n-x4);
            x4=n;
            q.push(t);
        }
    }

    int n2=2*n+n-x4;
    int x2=0;
    while(x2<n2 && !q.empty()){
        if(q.top()<2) break;
        int t=q.top();
        q.pop();
        if(t/2+x2<n2){
            x2+=t/2;
            t%=2;
            if(t) q.push(t);
        }else {
            t-=2*(n2-x2);
            x2=n2;
            q.push(t);
        }
    }

    int n3=n-x4+n2-x2;
    int x=0;
    while(!q.empty()){
        x+=q.top();
        q.pop();
    }
    if(x<=n3) puts("YES");
    else puts("NO");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值