0/1背包问题一维逆序解释

01背包问题

  • 有n件物品,每件物品的重量为w[i],价值为c[i]。
  • 现有容量为V(重量)的背包,
  • 问如何选取物品放入背包,
  • 使得背包内物品的总价值最大
  • 令dp[i][v]表示表示前i件物品恰好装入容量(重量)为v的背包中所能获得的最大价值
    *状态转移方程:
  • dp[i][v]=max(dp[i-1][v],dp[i-1][v-w[i]]+c[i])
  • 条件:1<=i<=n,w[i]<=v<=V
  • 边界条件:dp[0][v]=0,0<=v<=V
  • for(int i=1;i<=n;i++){
    for(int v=w[i];v<=V;v++){
    dp[i][v]=max(dp[i-1][v],dp[v-1][v-w[i]]+c[i]);
    }
    }
  • 变为一维状态转移方程,逆序原因:
  • 采用从右到左只会计算dp[i][v+1],不会覆盖掉dp[i][v],不会出错
  • 如果采用从左到右边,原dp[i-1][v]会被dp[i][v]覆盖掉,后面用的时候会出错了
  • dp[v]=max(dp[v],dp[v-w[i]]+c[i])
  • for(int i=1;i<=n;i++) {
    for (int v = V; v >= w[i]; v–){
    dp[v]=max(dp[v],dp[v-w[i]]+c[i])
    }
    }
#include 
#include
using namespace std;

const int maxn=100;
const int maxv=1000;
int w[maxn],c[maxn],dp[maxv];
int main()
{
     
    int n,V;
    scanf("%d%d",&n,&V);
    for(int i=1;i<=n;i++)
    {
     
        scanf("%d%d",&w[i],&c[i]);
    }
    fill(dp,dp+maxv,0);
    for(int i=1;i<=n;i++)
    {
     
        for(int v=V;v>=w[i];v--)
        {
     
            dp[v]=max(dp[v],dp[v-w[i]]+c[i]);
        }
    }
    cout<<dp[V]<<endl;
}

你可能感兴趣的:(算法)