Codeforces Round #810 (Div. 2) C.Color the Picture,大胆猜测+一点模拟

题目给定若干段颜色,还有每个颜色能涂的max个数

求能否满足相邻方格必须同一个颜色,规定相邻方格必定为4个,如果跨边界了也要考虑(比如第1行的上面的方块就是第n行

 

样例给出的染色方案是整列整列染过去,现场的时候思考了一下除了整列整行的染,有没有其他方案?

没有,因为如果有的话,必然存在锯齿一样的边界线,边界必有方格不能满足

那就只能整行或者整列地染色啦!——但是要怎么保证在每个颜色能染的数目>=2,且最后不会余出1行?

check的时候我优先判断当前需要几行,如果%2==1的话,那么就要先尽可能的凑出奇数,紧接着尽可能的拿最大偶数

比如说遇到了5吧,现在还缺偶数个,我们就拿4,同时tot+4,num+1,表示可支配但没选的多了一个(如果最后不够,那就把num都塞进本来可以呆的地方

如果最后已经选取的tot+num>=need,就符合条件~

 

小tips:如果没有开longlong的话,累加到符合条件就要break了,不会会爆炸hhh

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int r[int(1e5)+7],a[int(1e5)+7];
bool cmp(int a,int b){return a>b;}
bool work(int n,int m){
    for(int i=1;i<=k;i++) r[i]=a[i]/n;
    sort(r+1,r+k+1,cmp);
    int need=0,tot=0,left=0;
    need=m%2;
    for(int i=1;i<=k;i++){
        if(r[i]<=1) break;
        if(tot>=m) break;
        if(tot+1==m) break;
        if(r[i]%2==1){
            if(need==1) {tot+=r[i];need=0;}
            else {tot+=r[i]-1;left++;}
        }
        else {
            if(need==1){
                if(r[i]>=4){
                    tot+=r[i]-1;need=0;left++;
                }
                else if(r[i]==2) {
                    tot+=r[i];
                }
            }
            else tot+=r[i];
        }
    }
    if(tot+left>=m) return true;
    else return false;
}
void solve(){
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++) cin>>a[i];    
    if(work(n,m)||work(m,n)) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
}
int main(){
    //freopen("lys.in","r",stdin);
    int t;
    cin>>t;
    while(t--){
        solve();
    }
}

 

posted @ 2022-07-28 10:54  liyishui  阅读(79)  评论(0编辑  收藏  举报