其他分享
首页 > 其他分享> > HDU-2546 饭卡(01背包)

HDU-2546 饭卡(01背包)

作者:互联网

饭卡

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=2546
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

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


emmm。。。水题继续,这一题看起来好像不是背包,但由于万物就可dp,所以这一题转化一下也就成了01背包了。。。我们先扣去5元用于买最贵的,然后剩下的钱就是背包的容量上限了。当然它规定了5元以下没有购买力,所以我们才能用5元买最贵的(因为5元只能买一件东西就算是1 1,它也只能剩下4元)。。。
有了容量上限,和每个物品的重量,01背包也就出来了,当然,有些萌新可能会有些疑惑,那么我们的价值怎么算呢?
其实,这种情况下我们的价值和重量是一样的。这里的容量上限实际上是价值上限,而我们需要计算的就是在该价值上限下,他能去得的最大价值。。。于是我们得到了一个看起来有些别扭的式子: dp[j]=max(dp[j],dp[j-a[i]]+a[i]);(a[i]为价值)然后接下来就是标准的01背包套路:

for (int i=2; i<=n; i++) {
	for (int j=m; j>=a[i]; j--)
		dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
}

我们先排了个序,用5元买走了最大价值的所以i从2开始。。。
以下为AC代码:

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std; 
int a[1020];
bool cmp(int x,int y)
{
    return x>y;
}
int dp[1200];
int main()
{
    int n,m;
    while(scanf ("%d",&n)){
        if (n==0) return 0;
        memset(a,0,sizeof(a));
        for (int i=1; i<=n; i++){
            scanf ("%d",&a[i]);
        }
        memset(dp,0,sizeof(dp));
        scanf ("%d",&m);
        if (m<5) {
            printf ("%d\n",m);
            continue;
        }
        m-=5;
        sort(a+1,a+1+n,cmp);
        int sum=0,ans;
        sum+=a[1];
        for (int i=2; i<=n; i++){
            for (int j=m; j>=a[i]; j--)
               dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
        }
        sum+=dp[m];
        ans=m+5-sum;
        printf ("%d\n",ans);
    }
    return 0;
}

标签:HDU,01,饭卡,int,卡上,背包,余额,dp
来源: https://blog.csdn.net/qq_43906000/article/details/88630335