完全背包

来源:互联网 发布:c语言编写小游戏 编辑:程序博客网 时间:2024/06/05 06:12

完全背包问题

有n种重量和价值分别为wi和vi的物品,从这些物品种挑选总重量不超过W的物品,求出挑选物品价值总和的最大值。在这里,每种物品可以挑选任意都件。
限制条件:
1<= n <= 100
1<= wi,vi <= 100
1 <= W <= 10000
分析:
定义:dp[i+1][j] 前i种物品,总重量不超过j的最大价值和
状态:当w[i] < j 时 dp[i+1][j] = dp[i][j];
否则dp[i+1][j] = dp[i][j-k*w[i]]] + k*v[i] (k>=1)
两个可以合起来写成dp[i+1][j] = max(dp[i][j-k*w[i]]+k*v[i]) (k>=0)
这样写的递推关系是nW^2
有一个优化:可以发现dp[i+1][j] 的计算K个的时候,在计算dp[i+1][j-w[i]] 计算k-1个的时候已经完成了
于是就有如下变形:
max(dp[i][j-k*w[i]] + k*v[i]) (k>=0)
= max(dp[i][j],dp[i][j-k*w[i]]+k*v[i])(k>=1)
= max(dp[i][j],max(dp[i][(j-w[i])-k*w[i]]+k*v[i])+v[i])(k>=0)
= max(dp[i][j],dp[i+1][j-w[i]]+v[i])

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>using namespace std;const int maxn = 1e2+5;int dp[maxn][maxn];int w[maxn],v[maxn];int n,W;void solve(){    for(int i=0;i<=W;i++) dp[0][W] = 0;    for(int i=0;i<n;i++)    {        for(int j=0;j<=W;j++)        {            if(j<w[i])dp[i+1][j] = dp[i][j];            else dp[i+1][j] = max(dp[i][j],dp[i+1][j-w[i]]+v[i]);        }    }    printf("%d\n",dp[n][W]);}int main(){    scanf("%d%d",&n,&W);    for(int i=0;i<n;i++)    {        scanf("%d%d",&w[i],&v[i]);    }    solve();        return 0;}