01背包 hdu2546 hdu2602

来源:互联网 发布:mac pro垃圾桶 玩游戏 编辑:程序博客网 时间:2024/05/22 01:28


01背包的思想呢,也是dp的思想吧,把问题转化为子问题求解,不断继承状态得到最后的答案。


贴个公式:f[i][v]=max(f[i-1][v],f[i-1][v-c[i]]+w[i]);f[i][v]表示的是前i件物品放在一个容量为v的背包里可以获得的最大值。我也不明白这个二维数组的实用性在哪里,我都是写一维的数组,也弱的只会一维的勒,然后一维的话,两个for循环,第一个循环的是物品的第几个第几个,第二个循环是背包的重量,此处重点是,第二个循环是逆序的循环,是从背包的最大值开始的,因为呢,继承的值是一次的,学长当时讲的是自下而上,自左向右填表的,当时我模拟填表的时候换行填时,是先从v=v开始找[v-w[i]]的,而不是从v=0开始找的,然后在比较权值能不能改变,之后再进行继承那个较大的值,所以我觉得这里逆序的可以这样理解,算是强行理解下吧。

一维是优化过(空间)的:dp[v]=max(dp[v],dp[v-a[i]]+val[i]);a[i]是物品的在背包里需要占有的背包容量,可以是重量啊,体积啊什么的。val[i]是物品的权值。

然后贴题目和代码:hdu 2546

Problem Description
电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
 

Input
多组数据。对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。

n=0表示数据结束。
 

Output
对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。
 

Sample Input
1505101 2 3 2 1 1 2 3 2 1500
 

Sample Output
-4532

把剩下的那个五块钱单独拿出来买价值最大的物品就行啦:

#include<bits/stdc++.h>
using namespace std;
int cmp(int a,int b)
{
    return a<b;
}
int main()
{
    int dp[1005],a[1005];
    int n,m,i,j;
    while(scanf("%d",&n)&&n)
    {
        memset(dp,0,sizeof(dp));
        memset(a,0,sizeof(a));
        for(i=0;i<n;i++)
            scanf("%d",&a[i]);


        scanf("%d",&m);
        sort(a,a+n,cmp);
        if(m<5)
        {
            cout<<m<<endl;
            continue;
        }
        m-=5;
        for(i=0;i<n-1;i++)
            for(j=m;j>=a[i];j--)
                dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
        //cout<<dp[45]<<" "<<a[n-1]<<endl;
        cout<<m-dp[m]+5-a[n-1]<<endl;
    }
    return 0;
}


还有个模板题 hdu 2602:


Problem Description
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
15 101 2 3 4 55 4 3 2 1
 

Sample Output
14

记性太差,模板过也贴一下把:

#include<bits/stdc++.h>
using namespace std;


int main()
{
    int dp[1005],a[1005],b[1055];
    int n,m,i,j,v,t;
    scanf("%d",&t);
    while(t--)
    {
        //memset(a,0,sizeof(a));
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&n,&v);
        for(i=0;i<n;i++)
            scanf("%d",&a[i]);
        for(i=0;i<n;i++)
            scanf("%d",&b[i]);
        for(i=0;i<n;i++)
            for(j=v;j>=b[i];j--)
        dp[j]=max(dp[j],dp[j-b[i]]+a[i]);
        cout<<dp[v]<<endl;
    }
    return 0;
}


0 0
原创粉丝点击