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;
    }

  • 相关阅读:
    信号与系统04 离散时间傅里叶变换
    什么是吉布斯现象
    部分分式展开
    常见的傅里叶变换对
    微分运算的时域扩展
    动态库和静态库的制作与使用 【转载】原文链接https://www.cnblogs.com/WindSun/p/11287927.html
    派生访问说明符
    自定义异常类
    C++虚函数
    Linux知识点
  • 原文地址:https://www.cnblogs.com/Ritchie/p/5380213.html
Copyright © 2011-2022 走看看