小记: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; }