zoukankan      html  css  js  c++  java
  • 0-1背包专题

     
     
     
     
    话不多说,直接上题,先来一个 ,  01背包的入门题 
     
     
     
     
    Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave …
    The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ?
     
    Input
    The first line contain a integer T , the number of cases.
    Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.
     
    Output
    One integer per line representing the maximum of the total value (this number will be less than 231).
     
    Sample Input
    1
     
    5 10
     
    1 2 3 4 5
     
    5 4 3 2 1
     
    Sample Output
     
    14
     
     
     
     
     
    题目意思是:   第一行是测试次数T,接下来就是 n(骨头数)  和   volume (背包容量)   ,后面一行连续输入   n个数(1~n),代表相应骨头的价值  ,最后一行则是输入,n个数 , 相应骨头的体积。  输出背包能装下的最高价值。
     
     
     
    ac代码:
     
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<stack>
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define Swap(a,b,t) t=a,a=b,b=t
    #define Mem0(x) memset(x,0,sizeof(x))
    #define Mem1(x) memset(x,-1,sizeof(x))
    #define MemX(x) memset(x,0x3f,sizeof(x));
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f;
    const double eps=1e-12;
    int n,w,c[1010],v[1010]; 
    ll dp[1010];
    int main()
    {
        int T;
        cin>>T;
        while (T--){
            Mem0(dp);
            cin>>n>>w;
            for (int i=1;i<=n;i++)
                cin>>c[i];
            for (int i=1;i<=n;i++)
                cin>>v[i];
            for (int i=1;i<=n;i++){
                for (int j=w;j>=v[i];j--){
                    dp[j]=Max(dp[j],dp[j-v[i]]+c[i]);   //01背包的核心     dp[j]  代表  容量 j, 能装下的价值最大值   ,所以最后dp[背包体积]  就是背包能装下的最大价值     
                }
            }
            cout<<dp[w]<<endl;
        }
        return 0;
    }



    题目2: hdu 2546 http://acm.hdu.edu.cn/showproblem.php?pid=2546





    Problem Description
    
    
    电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
    某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
    
    
     
    
    
    Input
    
    
    多组数据。对于每组数据:
    第一行为正整数n,表示菜的数量。n<=1000。
    第二行包括n个正整数,表示每种菜的价格。价格不超过50。
    第三行包括一个正整数m,表示卡上的余额。m<=1000。

    n=0表示数据结束。
    
    
     
    
    
    Output
    
    
    对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。
    
    
     
    
    
    Sample Input
    
    
    1
    50
    5
     
     
     
    10
    1 2 3 2 1 1 2 3 2 1
    50
     
     
     
    0
    
    
     
    
    
    Sample Output
    
    
    -45
     
     
    32


    a
    c代码: //与第一题类似,就不讲了。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<stack>
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define Swap(a,b,t) t=a,a=b,b=t
    #define Mem0(x) memset(x,0,sizeof(x))
    #define Mem1(x) memset(x,-1,sizeof(x))
    #define MemX(x) memset(x,0x3f,sizeof(x));
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f;
    const double eps=1e-12;
    int p[1010],dp[1010];
    int main()
    {
        int n,v,vv,i,j,temp;;
        while (cin>>n&&n){
            Mem0(dp);
            int max=-inf;
            for (i=1;i<=n;i++){
                cin>>p[i];
                if (max<p[i]){
                    max=p[i];
                    temp=i;
                }    
            }
            cin>>vv;
            v=vv;
            if (v<5){
                cout<<v<<endl;
                continue;
            }
            else{
                v-=5;
                p[temp]=0;
                for (i=1;i<=n;i++){
                    for (j=v;j>=p[i];j--){
                        dp[j]=Max(dp[j],dp[j-p[i]]+p[i]);
                    }
                }
            }
            cout<<vv-dp[v]-max<<endl;
        }
        return 0;
    }

    hdu 1171   http://acm.hdu.edu.cn/showproblem.php?pid=1171
    Problem Description
    
    
    Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe you don't know that Computer College had ever been split into Computer College and Software College in 2002.
    The splitting is absolutely a big event in HDU! At the same time, it is a trouble thing too. All facilities must go halves. First, all facilities are assessed, and two facilities are thought to be same if they have the same value. It is assumed that there is N (0<N<1000) kinds of facilities (different value, different kinds).
    
    
     
    
    
    Input
    
    
    Input contains multiple test cases. Each test case starts with a number N (0 < N <= 50 -- the total number of different facilities). The next N lines contain an integer V (0<V<=50 --value of facility) and an integer M (0<M<=100 --corresponding number of the facilities) each. You can assume that all V are different.
    A test case starting with a negative integer terminates input and this test case is not to be processed.
    
    
     
    
    
    Output
    
    
    For each case, print one line containing two integers A and B which denote the value of Computer College and Software College will get respectively. A and B should be as equal as possible. At the same time, you should guarantee that A is not less than B.
    
    
     
    
    
    Sample Input
    
    
    2
    10 1
    20 1
     
     
    3
    10 1
    20 2
    30 1
     
     
    -1
    
    
     
    
    
    Sample Output
    
    
    20 10
     
    40 40



    ps: 题意: 输出物体种数n , 然后接下来就是n行 分别代表其的价值 和 该物的数目。


        这题也基本和题目1一样,只要注意,求出总价值sum,然后假装有一个体积为sum/2的背包, 求出能装下的最大价值。 (记住题目要求输出的时候,要价值大的先输出)



    ac 代码:


    方法1: 化作  纯 01背包 优:提高效率 缺:内存消耗大
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<stack>
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define Swap(a,b,t) t=a,a=b,b=t
    #define Mem0(x) memset(x,0,sizeof(x))
    #define Mem1(x) memset(x,-1,sizeof(x))
    #define MemX(x) memset(x,0x3f,sizeof(x));
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f;
    const double eps=1e-12;
    ll p[250010],dp[250010];
    int main()
    {
        ll n,m,v,sum,temp,i,j,cnt;
        while (cin>>n&&n>=0){
            Mem0(dp);
            sum=temp=0;
            for (i=1,cnt=1;i<=n;i++){      
                cin>>temp>>m;
                for (j=1;j<=m;j++){
                    p[cnt]=temp;
                    sum+=p[cnt++];
                }    
            }
            v=sum/2;
            for (i=1;i<cnt;i++){
                for (j=v;j>=p[i];j--){
                    dp[j]=Max(dp[j],dp[j-p[i]]+p[i]);
                }
            }
            cout<<sum-dp[v]<<" "<<dp[v]<<endl;
        }
        return 0;
    }
    方法2: 相比1   优:内存少   缺:耗时高       但是两者都能ac

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<stack>
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define Swap(a,b,t) t=a,a=b,b=t
    #define Mem0(x) memset(x,0,sizeof(x))
    #define Mem1(x) memset(x,-1,sizeof(x))
    #define MemX(x) memset(x,0x3f,sizeof(x));
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f;
    const double eps=1e-12;
    int p[250010],dp[500010],num[55];
    int main()
    {
        int n,m,v,sum,i,j;
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        while (cin>>n&&n>=0){
            Mem0(dp);
            sum=0;
            for (i=1;i<=n;i++){
                cin>>p[i]>>num[i];
                sum+=(p[i]*num[i]);            
            }
            v=sum/2;
            for (i=1;i<=n;i++){
                for (int tt=0;tt<num[i];tt++)
                for (j=v;j>=p[i];j--){
                    dp[j]=Max(dp[j],dp[j-p[i]]+p[i]);
                }
            }
            cout<<sum-dp[v]<<" "<<dp[v]<<endl;
        }
        return 0;
    }


  • 相关阅读:
    Pytorch学习(一)基础语法篇
    CSAPP深入理解计算机系统(第二版)第三章家庭作业答案
    理解DP(持续更新)
    LeetCode题解 | 215. 数组中的第K个最大元素
    快速排序
    浅谈设计模式(java)——从lol来看观察者模式
    <小虾米的android学习之旅1>Android框架
    程序员如何用技术变现?
    为了反击爬虫,前端工程师的脑洞可以有多大?
    如何成为一名爬虫工程师?(顺带提供工作机会)
  • 原文地址:https://www.cnblogs.com/q1204675546/p/9361430.html
Copyright © 2011-2022 走看看