zoukankan      html  css  js  c++  java
  • 《趣学算法》动态规划 大卖场购物车1——01背包问题

    2019-11-30

    10:05:54

    如何把背包问题画一幅DAG呢?这是自己最近很困惑的。想看看到底这个DAG是啥样!

    #include <bits/stdc++.h>
    #include <stdlib.h>
    #include <stdio.h>
    using namespace std;
    #define maxn 10005
    #define M 105
    int c[M][maxn];
    int w[M],v[M];
    int x[M];//x[M]表示第i个物品是否放入购物车
    int main(){
        int i,j,n,W;
        cout<<"请输入物品的个数: ";
        cin>> n;
        cout<<"请输入购物车的容量:";
        cin>>W;
        cout<<"请输入每个物品的重量w 和 价值 v,用空格分开:";
        for(int i=1;i<=n;++i){
            cin>>w[i]>>v[i];
        }
        for(i=0;i<=n;++i){
            c[i][0]=0;
        }
        for(j=0;j<=W;++j){
            c[0][j] = 0;
        }
        for(i=1;i<=n;++i){
            for(int j=1;j<=W;++j){
                if(j<w[i]){//当物品重量大于购物车容量时,不放入 
                    c[i][j] = c[i-1][j];
                }
                else{
                    c[i][j] = max(c[i-1][j],c[i-1][j-w[i]]+v[i]);
                }
            }
        }
        cout<<"装入购物车的最大价值为: "<<c[n][W]<<endl;
        //逆向构造最优解
        j = W;
        for(i=n;i>0;--i){
            if(c[i][j]>c[i-1][j]){
                x[i]=1;
                j -= w[i];
            }else{
                x[i] = 0;
            }
        }
        cout<<"装入购物车的物品为:"<<endl;
        for(int i=1;i<=n;++i){
            if(x[i]==1){
                cout<<i<<" ";
            }
        }
        system("pause");
        return 0;
         
    } 

     优化成一维数组:

     逆序的关键是:如果是正序,则求f[v]时,f[0],...f[v-1]都已经改变过!里面存的不是i-1时刻的值。这样求f[v]时必定是错误的!

    看一下错误的正序时的结果:

     这是正确的逆序时的结果:

    #include <bits/stdc++.h>
    #include <stdlib.h>
    #include <stdio.h>
    using namespace std;
    #define maxn 10005
    #define M 105
    int  dp[maxn];//dp[i]表示当前已放入容量为j 的购物车获得的最大价值
    int w[M],v[M];
    int x[M];//x[i]表示第i个物品是否放入购物车
    int i,j,n,W;//n表示n个物品,W表示购物车容量
    void opt1(int n,int W){
        for(int i=1;i<=n;++i){
            for(j=W;j>0;--j){
                if(j>=w[i]){
                    dp[j] = max(dp[j],dp[j-w[i]]+v[i]);
                }
            }
        }
    } 
     
    int main(){
        cout<<"请输入物品的个数: ";
        cin>>n;
        cout<<"请输入购物车的容量: ";
        cin>>W;
        cout<<"请依次输入每个物品的重量w和价值v,用空格分开: ";
        for(int i=1;i<=n;++i){
            cin>>w[i]>>v[i];
        }
        for(int j=1;j<=W;++j){
            dp[j] = 0;//初始化第0行为0; 
        }
        opt1(n,W);
        cout<<"装入购物车的最大价值为:"<<dp[W]<<endl;
        //测试dp[]数组结果
        for(j=1;j<=W;++j){
            cout<<dp[j]<<" "; 
        } 
        cout<<endl;
        system("pause");
        return 0;
         
    } 
  • 相关阅读:
    C#读写XML no
    ComboBox、ListBox绑定和获取数据 no
    win7 安装oracle 11g no
    2011没有惊天动地 no
    Oracle 删除重复数据只留一条 no
    Oracle 创建用户并分配权限 no
    Oracle 导出、导入某用户所有数据(包括表、视图、存储过程...) no
    谢谢,博客园这么快就审批通过了我的申请!
    Eclipse 中 JAVA AWT相关包不提示问题(解决)
    Eclipse java项目转Maven项目
  • 原文地址:https://www.cnblogs.com/JasonPeng1/p/11961516.html
Copyright © 2011-2022 走看看