P6775 [NOI2020] 制作菜品

P6775 [NOI2020] 制作菜品

链接

P6775 [NOI2020] 制作菜品

题解

分三种情况讨论:
1.m=n-1,就是alias method。。(NOI考的算法越来越怪啦QAQ),这里是\(O(n)\)的。
2.m>=n,这个时候一定存在某些材料不小于K克,强行用这个材料减K,这样m减少1,n可能不变可能减1。不断重复就能做完或者变成1情况。\(O(n)\)
3.m=n-2,有解的情况当且仅当可以分成两个1情况。可以\(O(n^2k)\)DP,用bitset优化就能通过这题了。

\(Code\)

#include<bits/stdc++.h>
using namespace std;
const int N=5005;
const int M=5005*505;
int n,m,K;
struct Node{
    int id;
    int V;
}a[N];
int v[N];
int cnt;
struct ANS{
    int idx,Vx;
    int idy,Vy;
}b[N];
vector<Node> c,d;
void sol(vector<Node> A){
    c.clear();d.clear();
    for(int i=0;i<A.size();++i){
        if(A[i].V>=K) d.push_back(A[i]);
        else c.push_back(A[i]);
    }
    int i=0,j=0;Node tmp;
    while(i<c.size()){
        tmp=c[i];++i;
        ++cnt;b[cnt].idx=tmp.id;b[cnt].Vx=tmp.V;
        if(j<d.size()){
            b[cnt].idy=d[j].id;b[cnt].Vy=K-tmp.V;
            d[j].V-=b[cnt].Vy;
            if(d[j].V<K){
                c.push_back(d[j]);
                ++j;
            }
        }
        else{
            b[cnt].idy=c[i].id;b[cnt].Vy=K-tmp.V;
            c[i].V-=b[cnt].Vy;
            if(c[i].V==0) ++i;
        }
    }
    return;
}

bitset<M+M+1> f[505];
vector<Node> q1,q2;
void MAIN(){
    scanf("%d%d%d",&n,&m,&K);
    for(int i=1;i<=n;++i) {
        a[i].id=i;
        scanf("%d",&a[i].V);
    }
    cnt=0;
    for(int i=1;i<=m;++i){
        b[i].idx=b[i].Vx=b[i].idy=b[i].Vy=0;
    }
    int l=1;
    while(n<=m&&m>0){
        while(a[l].V<K)++l;
        ++cnt;
        b[cnt].idx=a[l].id;
        b[cnt].Vx=K;
        m--;
        a[l].V-=K;
        if(a[l].V==0){
            swap(a[l],a[n]);
            --n;
        }
    }
    if(m>0){
        if(m==n-2){
            for(int i=1;i<=n;++i) v[i]=a[i].V-K;
            f[0].reset();
            f[0].set(M);
            for(int i=1;i<=n;++i){
                f[i]=f[i-1];
                if(v[i]>=0) f[i]|=f[i-1]<<v[i];
                else f[i]|=f[i-1]>>(-v[i]);
            }
            if(!f[n][M-K]){
                puts("-1");
                return;
            }
            q1.clear();q2.clear();
            int now=M-K;
            for(int i=n;i>=1;--i){
                if(f[i-1][now-v[i]]){
                    q1.push_back(a[i]);
                    now=now-v[i];
                }
                else{
                    q2.push_back(a[i]);
                }
            }
            sol(q1);sol(q2);
        }
        else if(m==n-1){
            q1.clear();
            for(int i=1;i<=n;++i) q1.push_back(a[i]);
            sol(q1);
        }
    }
    for(int i=1;i<=cnt;++i){
        printf("%d %d",b[i].idx,b[i].Vx);
        if(b[i].idy) printf(" %d %d",b[i].idy,b[i].Vy);
        puts("");
    }
    return;
}
int main(){
    int ttt=1;scanf("%d",&ttt);
    while(ttt--) MAIN();
    return 0;
}
posted @ 2021-04-18 15:17  Iscream-2001  阅读(44)  评论(0编辑  收藏  举报
/* */