zoukankan      html  css  js  c++  java
  • 关于01背包问题优化的时候为什么不能正向跑

    假设有两个物品 第一个物品 w=2 v=1 第二个物品 w=2 v=2
    在将背包由二维转化为一维进行优化的时候
    如果正常逆序进行dp
    dp[1][4]=1; dp[1][2]=1; dp[2][4]=max(dp[1][4],dp[1][4-2]+2)=3; dp[2][2]=2;
    这是正确做法
    但是如果正序进行dp
    do[1][4]=1; dp[1][2]=1; dp[2][2]=2; dp[2][4]=max(dp[1][4],dp[2][4-2]+2)=4;
    注意上面为dp[1][4-2]而下面为dp[2][4-2]     原因是dp[2][2]已更新

    出错的原因就是 第二个物品取了两次 其实这也就是完全背包的来源
    就是dp[i][j]由dp[i][j-w[i]]+v[i]推过来的 而不是dp[i-1][j-w[i]]+v[i]
    会导致结果偏大

    最初的想法为顺序会更对 结果更大更准确
    经代码验证想法错误 但是发现了完全背包
    下一步多重背包
    以下为验证代码:

    #include <iostream>
    #include <string.h>
    using namespace std;
    int dp[1005];
    int main()
    {
    int i,j,n,m,t;
    int v[1005]={0};
    int w[1005]={0};
    cin>>t;
    while(t--)
    {
    cin>>n>>m;
    memset(dp,0,sizeof(dp));
    memset(v,0,sizeof(v));
    memset(w,0,sizeof(w));
    for(i=1;i<=n;i++)
    cin>>v[i];
    for(i=1;i<=n;i++)
    cin>>w[i];

    //正确的逆向跑
    for(i=1;i<=n;i++)
    {for(j=m;j>=w[i];j--)
    {
    dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    cout<<dp[j]<<" ";
    }cout<<endl;
    }
    cout<<endl<<endl;

    //错误的正向跑
    memset(dp,0,sizeof(dp));
    for(i=1;i<=n;i++)
    {for(j=w[i];j<=m;j++)
    {
    dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    cout<<dp[j]<<" ";
    }cout<<endl;
    }
    cout<<endl;
    //cout<<dp[m]<<endl;
    }
    return 0;
    }

  • 相关阅读:
    jdbc代码
    openwrt vsftp
    openwrt 配置samba && ubuntu 配置samba
    如何学习开源项目
    Makefile 笔记
    Samba 学习笔记
    quilt-补丁工具
    to-do-list
    新增feeds模块
    linux命令
  • 原文地址:https://www.cnblogs.com/Ritchie/p/5380213.html
Copyright © 2011-2022 走看看