洛谷【P1064】金明的预算方案

浅谈\(DP\)https://www.cnblogs.com/AKMer/p/10437525.html

题目传送门:https://www.luogu.org/problemnew/show/P1064

分组背包:https://www.cnblogs.com/AKMer/p/10437699.html

这种问题又叫做有依赖性的背包问题,此题难度还不是很高,更有甚者可以依赖关系多搞几层。

我们只需要把一个主件搭配附件的若干种方案全部单独拎出来,每种方案看做是一个物品,这些物品是分组背包里的同一个组,然后做一遍分组背包即可。

时间复杂度:\(O(nm)\)

空间复杂度:\(O(n)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=32005;

int n,m;
int f[maxn];
int w[100][5],v[100][5];

int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

int main() {
    n=read(),m=read();
    for(int i=1;i<=m;i++) {
        int W=read(),V=read(),t=read();
        if(!t)w[i][0]=1,w[i][1]=W,v[i][1]=W*V;
        else {
            for(int j=1;j<=w[t][0];j++) {
                w[t][j+w[t][0]]=w[t][j]+W;
                v[t][j+w[t][0]]=v[t][j]+W*V;
            }
            w[t][0]<<=1;
        }
    }
    for(int i=1;i<=m;i++)
        for(int j=n;j;j--)
            for(int k=1;k<=w[i][0];k++) {
                if(j<w[i][k])continue;
                f[j]=max(f[j],f[j-w[i][k]]+v[i][k]);
            }
    printf("%d\n",f[n]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AKMer/p/10437705.html