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;
         
    } 
  • 相关阅读:
    Android--判断是否连接成功了指定wifi
    Android--判断listview上下滑动的方法
    Android--获取高清的app图标
    Android--px(像素)和dp、sp之间的相互转化
    Android--自定义半圆环型进度(带动画)
    Android--将实体类转化成Json和Map的基类
    Android--自定义控件---自动分页的GridView
    Android--解决EditText放到popupWindow中,原有复制、粘贴、全选、选择功能失效问题
    Android--仿一号店货物详情轮播图动画效果
    Switch-case 内定义变量的问题
  • 原文地址:https://www.cnblogs.com/JasonPeng1/p/11961516.html
Copyright © 2011-2022 走看看