小记:1A,
思路:二维完全背包。看数据,本来以为需要三维dp的,后来想了一下,只要二维就可以解决了。
dp[i][j] 表示杀i个怪用了j点耐久度能获得的最大经验值
转移方程:
dp[i][j] = max(dp[i][j], dp[i-1][j - a[i].p] + a[i].v) (a[i].p是杀第i种怪要用掉的耐久度,a[i].v是杀第i种怪能得到的经验)
初始化都是0
最后的结果就是
只要dp[i][j]大于需要升级的经验值,那么就可以升级,然后看用了多少耐久度,保留最大的那个即可。
因为每种怪都是无限个的,所以是个完全背包问题。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
#define mst(a,b) memset(a,b,sizeof(a))
#define eps 10e-8
const int MAX_ = 110;
const int N = 100010;
const int INF = 0x7fffffff;
struct node {
int v,p;
} a[MAX_];
int dp[MAX_][MAX_];
int main() {
int n, m, k, s, ans, mmax;
while(~scanf("%d%d%d%d",&n,&m,&k,&s)) {
for(int i = 0; i < k; ++i) {
scanf("%d%d",&a[i].v,&a[i].p);
}
mst(dp,0);
ans = -1;
for(int i = 0; i < k; ++i) {
for(int j = 1; j <= s; ++j) {
for(int r = 0; r <= m; ++r) {
if(r - a[i].p >= 0) {
dp[j][r] = max(dp[j][r], dp[j-1][r - a[i].p] + a[i].v);
}
}
}
}
for(int i = 1; i <= s; ++i) {
for(int j = 0; j <= m; ++j) {
if(dp[i][j] >= n) {
ans = max(ans,m - j);
}
}
}
printf("%d\n",ans);
}
return 0;
}