SOJ 2222: Health Power http://acm.scu.edu.cn/soj/problem.action?id=2222
题目意思不难理解:给出需要的能量K以及F个食物(每个食物只能用一次),每种食物i具有能量HP[i]和分数score[i]。食物应该首先满足能量要求,然后从剩下的食物中获取分数。问在满足能量需求的条件下,能获取的最大能量是多少。
解题思路:我们只需找出满足能量同时分数之和最小的食物。定义dp[j]为能量等于j时最小的分数,那么我们有
dp[j]=min{dp[j-HP[i]]+score[i],dp[j]}
由于每种食物只能用一次,所以是一个0-1背包问题。把经典的0-1背包简单地修改一下即可。注意初始化。
代码如下:
#include<iostream> #include<algorithm> using namespace std; int HP[10005]; int score[10005]; int dp[11005]; int main() { int N, K, F; scanf("%d", &N); int i, j; int con = 100000001; int temp; int sum; int sum_temp; while (N--) { scanf("%d%d", &K, &F); sum = 0; sum_temp = 0; for (i = 0; i < F; i++) { scanf("%d%d", &HP[i], &score[i]); sum_temp += HP[i]; sum += score[i]; } if (sum_temp < K) { printf("0\n"); continue; } dp[0] = 0; for (i = 1; i <= K + 10000; i++) dp[i] = con; temp = con; for (i = 0; i < F; i++) for (j = K + 10000; j >= HP[i]; j--) { dp[j] = min(dp[j - HP[i]] + score[i], dp[j]); if (j >= K && dp[j] < temp) temp = dp[j]; } printf("%d\n", sum - temp); } return 0; }