• 背包入门(01背包,完全背包,多重背包)


    推荐一篇好文章:http://blog.csdn.net/sj13051180/article/details/6687674

    0-1背包,每件物品只有一个,对于每件物品只有取与不取两种情况,

    完全背包,每件物品无数多个,对于每件物品可以取任意多个。

    多重背包,每件物品有限多个,对于每件物品可以取任意多个。

    以poj-3624与poj-1276为原型,阐释三种背包的代码。

    0-1背包:

    #include <iostream>
    #include <stdio.h>
    using namespace std;
    int main(){
        int dp[12900];
        int n,m;
        int v[3405];
        int w[3405];
        while(cin >> n >> m){
            for(int j=0;j<=m;j++)
                dp[j]=0;
            for(int i=1;i<=n;i++)
                cin >> w[i] >> v[i];
            for(int i=1;i<=n;i++)
                for(int j=m;j>=w[i];j--)
                    dp[j] = max(dp[j],dp[j-w[i]]+v[i]);
            for(int j=0;j<=m;j++){
                cout << dp[j] <<" ";
            }
            cout <<endl;
            cout << dp[m] <<endl;
        }
        return 0;
    }

    完全背包:

    #include <iostream>
    #include <stdio.h>
    using namespace std;
    int main(){
        int dp[12900];
        int n,m;
        int v[3405];
        int w[3405];
        int num[3405];
        while(cin >> n >> m){
            for(int j=0;j<=m;j++)
                dp[j]=0;
            for(int i=1;i<=n;i++)
                cin >> w[i] >> v[i] ;
            for(int i=1;i<=n;i++)
                for(int k=1;k<=m/w[i];k++)
                    for(int j=k*w[i];j<=m;j++)
                        dp[j]=max(dp[j],dp[j-k*w[i]]+k*v[i]);
            for(int j=0;j<=m;j++){
                cout << dp[j] <<" ";
            }
            cout <<endl;
            cout << dp[m] <<endl;
        }
        return 0;
    }

    多重背包:

    三重循环,二维数组暴力解法(超时,超空间)

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    int dp[1406][1090];
    int main(){
    
        int n,m;
        int v[3405];
        int w[3405];
        int num[3405];
        while(cin >> n >> m){
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++)
                cin >> w[i] >> v[i] >>num[i];
            for(int i=1;i<=n;i++)
                for(int k=1;k<=num[i];k++)
                    for(int j=m;j>=k*w[i];j--)
                        dp[i][j]=max(dp[i-1][j],dp[i-1][j-k*w[i]]+k*v[i]);
            for(int i=0;i<=n;i++){
                for(int j=0;j<=m;j++){
                    cout << dp[i][j] << " ";
                }
                cout << endl;
            }
            cout << dp[n][m] <<endl;
        }
        return 0;
    }

    三重循环,一位数组(超时)

    实现时,用临时的一维数组暂存i-1层物品的价值。

    #include <string.h>
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    int main(){
        int dp[12900];
        int temp[12900];
        int n,m;
        int v[3405];
        int w[3405];
        int num[3405];
        while(cin >> n >> m){
            memset(dp,0,sizeof(dp));
            memset(temp,0,sizeof(temp));
            for(int i=1;i<=n;i++)
                cin >> w[i] >> v[i] >>num[i];
            for(int i=1;i<=n;i++){
                for(int j=0;j<=m;j++){
                    cout << dp[j] <<" ";
                }
                cout << endl;
                for(int i=0;i<=m;i++)
                    temp[i]=dp[i];
                for(int k=1;k<=num[i];k++){
                    for(int j=m;j>=k*w[i];j--){
                        dp[j]=max(dp[j],temp[j-k*w[i]]+k*v[i]);
                    }
                }
            }
            for(int j=0;j<=m;j++){
                cout << dp[j] <<" ";
            }
            cout << endl;
            cout << dp[m] <<endl;
        }
        return 0;
    }
    /*
    3 5
    1 60 2
    2 100 2
    3 120 2
    
    0 0 0 0 0 0
    0 60 120 120 120 120
    0 60 120 160 220 260
    0 60 120 160 220 260
    260
    */

    双重循环,一位数组(省时省空间)

    二进制压缩,把多数量的每种物品划分成单数量的多种物品,再运用0-1背包求解。

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    using namespace std;
    int dp[100005];
    int w[1000];
    int main(){
        int n,m,a,b,cnt;
        while(cin >> n >> m){
            cnt=0;
            memset(dp,0,sizeof(dp));
            memset(w,0,sizeof(w));
            for(int i=1;i<=m;i++){
                cin >> a >> b;
                for(int j=1;j<=a;j*=2){
                    w[++cnt]=j*b;
                    a-=j;
                }
                if(a>0){
                    w[++cnt]=a*b;
                }
            }
            for(int i=1;i<=cnt;i++)
                for(int j=n;j>=w[i];j--)
                    dp[j]=max(dp[j],dp[j-w[i]]+w[i]);
            cout << dp[n] <<endl;
        }
        return 0;
    }
  • 相关阅读:
    2017-3-31 操作属性 定时器 操作内容 操作相关元素 元素创建添加删除
    2017-3-30 Js实现导航栏,选项卡,图片轮播的制作
    2017-3-30 DOM查找元素 点击,鼠标移入,移除事件 样式控制
    Js产生随机数的几种方法
    2017-3-29 Js语法 DOM操作
    纯【css下拉菜单】
    2017-3-25 css样式表 去除按钮点点击是的绿色边框
    2017-3-23 网页中的表单 框架 标题栏小图标 描点 插入视频音频 简单的滚动条 css样式表
    【2017-2-21】C#分支语句,分支嵌套,变量的作用域
    【2017-2-20】C#运算符
  • 原文地址:https://www.cnblogs.com/markliu/p/2795921.html
Copyright © 2020-2023  润新知