动态规划---01背包

1、饭卡 hdu2546

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

//√31ms 01背包的应用,要变形也变的是输出结果,不是背包模板!
/*
theme:有一张饭卡,给定原始余额为m,食堂规定只要余额>=5就可以购买任意价格的菜,及时减掉之后余额为负
,否则无法购买,及时钱够。现给定n种菜的价格,问可以使卡的余额达到最低多少?(多组案例)
input:多组数据。对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。
n=0表示数据结束。
output:
对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。
*
*
*
*
*
*
solution:因为01背包算的是余额为i的背包能装下的最大物品(价值),所以我们可以
做减法,算出余额为i的卡最多能消费多少钱,再用开始余额减就可以得到最小余额
有一点要注意就是有个5元的限制条件,所以先利用贪心思想,从m元中拿出5元来买最贵的菜,
再用01背包算m-5的最大消费;一个菜
当然,如果m一开始就小于5则直接输出m(的d[m-5]会错!)
*/

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdlib.h>
#include<cstring>
#include<queue>
using namespace std;

const int Max=1010;
int price[2000];
int dp[2000];

void zeroOneKnapsack(int maxv,int costs,int gains)
{
    for(int i=maxv;i>=costs;--i)
        dp[i]=max(dp[i],dp[i-costs]+gains);
}

int main()
{
    int n;
    while(scanf("%d",&n)&&n)
    {
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;++i)
            scanf("%d",&price[i]);
        sort(price,price+n);
        int m;
        scanf("%d",&m);
        if(m<5){
            printf("%d\n",m);
            continue;
        }
        for(int i=0;i<n-1;++i)
            zeroOneKnapsack(m,price[i],price[i]);
        printf("%d\n",m-dp[m-5]-price[n-1]);
    }
}
/*
1
50
5
10
1 2 3 2 1 1 2 3 2 1
50
1
4
3
0

-45
32
3
*/

此题还可计算一下所有菜价格之和,若<m则输出m-accumulate(price,price+n,0)

猜你喜欢

转载自blog.csdn.net/wangqianqianya/article/details/82811766