题目链接: 点击打开链接
题目大意: 饭卡余额m元,从n道菜中选,使得饭卡余额尽量低,也就是花费尽量高。余额小于5元是买不了菜的,不低于5元的话就算透支也没事
思路: 动态规划,01背包
分析:
就是个01背包题,不过得做点变通。用一维数组dp存放子状态结果,dp[j]表示余额为j时最高的花费。那么dp[0]到dp[4]就永远都是0了。考虑到透支是可以的,所以在状态转移的时候,计算dp[j - price[i]]+price[i],如果j - price[i]小于0,那么dp[j - price[i]]就等于0(表明负数的余额下花费为0)
此外还有一点,花费的数目多少和买菜顺序也有关,先买贵的使余额降到5以下,就不能继续买了,所以一开始要对价格排个序。
代码:
#include <cstdio>
#include <algorithm>
#include <memory.h>
using namespace std;
const int maxn = 1000 + 10;
const int maxm = 1000 + 10;
int n, m;
int dp[maxm], price[maxn];
void solve()
{
memset(dp, 0, sizeof(dp));
for (int i = n; i >= 1; --i)
for (int j = m; j >= 5; --j) {
if (j >= price[i])
dp[j] = max(dp[j], dp[j-price[i]] + price[i]);
else
dp[j] = max(dp[j], price[i]);
}
}
int main()
{
while (scanf("%d", &n) && n != 0) {
for (int i = 1; i <= n; ++i)
scanf("%d", &price[i]);
sort(price+1, price+n+1);
scanf("%d", &m);
solve();
printf("%d\n", m - dp[m]);
}
return 0;
}