http://acm.hdu.edu.cn/showproblem.php?pid=2159
参考《背包九讲》第5讲
注意循环时,每次先杀一只怪,再选择不同的忍耐消耗。
可以利用循环的特点,省去无法升级的判断和相应输出。
完整代码:
/*0ms,276KB*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 105;
int exp[maxn], p[maxn];
int dp[maxn][maxn];
int main()
{
int n, m, k, s, minp, i, j;
while (~scanf("%d%d%d%d", &n, &m, &k, &s))
{
for (i = 0; i < k; i++)
scanf("%d%d", &exp[i], &p[i]);
memset(dp, 0, sizeof(dp));
for (minp = 1; minp <= m; ++minp)
{
for (i = 1; i <= s; i++)/// 先杀一只怪
for (j = 0; j < k; j++)/// 选择不同的怪,获得不同的经验,消耗不同的忍耐度
if (minp >= p[j])
dp[minp][i] = max(dp[minp][i], dp[minp - p[j]][i - 1] + exp[j]);
if (dp[minp][s] >= n) break;
}
printf("%d\n", m - minp);
}
return 0;
}