HDU 2546 饭卡

题意:
说有一种饭卡的规定是这样的,只有在剩余钱数在5元或者5元以上才会购买成功,并且余额为负数也可以。
思路:
刚开始就想到了01背包,只要在求的时候限定一下就可以了,限定如果这个状态是小于5元的,上一个状态来源必须是大于5元的,然后求这个所有状态能达到的最大钱数。用本金减去这个钱数就是答案了。
排序使为了能使最大的钱数用在最后,这样的结果一定是最优的。
Code:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<list>
#include<map>
#include<set>

#define TEST

#define LL long long
#define Mt(f, x) memset(f, x, sizeof(f));
#define rep(i, s, e) for(int i = (s); i <= (e); ++i)
#ifdef TEST
    #define See(a) cout << #a << " = " << a << endl;
    #define See2(a, b) cout << #a << " = " << a << ' ' << #b << " = " << b << endl;
    #define debug(a, s, e) rep(_i, s, e) {cout << a[_i] << ' ';} cout << endl;
    #define debug2(a, s, e, ss, ee) rep(i_, s, e) {debug(a[i_], ss, ee)}
#else
    #define See(a)
    #define See2(a, b)
    #define debug(a, s, e)
    #define debug2(a, s, e, ss, ee)
#endif // TEST

const int MAX = 2e9;
const int MIN = -2e9;
const double eps = 1e-8;
const double PI = acos(-1.0);

using namespace std;

const int N = 2e3 + 5;

int f[N], a[N];
int money;

void zop(int value)
{
    for(int i = 1045; i >= 1000 - money; --i)
    {
        if(i - value <= 995 && i - value >= 1000 - money)
        {
            f[i] = max(f[i], f[i - value] + value);
        }
    }
}

int main()
{
    int n;
    while(~scanf("%d", &n) && n)
    {
        Mt(f, 0);
        for(int i = 0; i < n; ++i)
        {
            scanf("%d", &a[i]);
        }
        scanf("%d", &money);
        if(money < 5)
        {
            printf("%d\n", money);
            continue;
        }
        sort(a, a + n);
        for(int i = 0; i < n; ++i)
        {
            zop(a[i]);
        }
//        debug(f, 1000 - money, 1045);
        int ans = MIN;
        for(int i = 0; i <= 1045; ++i)
        {
            ans = max(ans, f[i]);
        }
        printf("%d\n", money - ans);
    }
    return 0;
}
/*
3
3
5
1
6
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值