小记:真是艹,自己想到了两重dp还写出了状态转移方程,在k的处理我本来是打算dp求完之后,剩下的最大的前k个 加上dp最大值 就是答案,但是那剩下的前k个不晓得怎么搞,所以两重我是解决不了了。 想了我头痛了,百度了一个题目,看到了四个字,立马就顿悟了啊。。。。三重dp!!!日后对于dp的题目还是要多做做,这就是做题不足的后果,再加一重即可,都没有想到,肯定是没加状态,我相信在比赛的时候有专注buff附身 应该绝对肯定能想到!!! 是的,肯定是这样。
思路:dp[k][i][j] 免费拿k个,花i块,花j积分 所能拿到的最大实际价值。
状态转移方程:
dp[k][i][j] = max(dp[k][i][j], dp[k-1][i][j], dp[k][i-price[t]][j], dp[k][i][j - score[t]]) (k > 0, i >= price[t] , j >= score[t], t = 1,2,3,4....n)
price[t]是第t种用现金要的的钱数,score[t]是第t种用积分兑换需要花的积分数。
代码:
#include <stdio.h>
#include <string.h>
#include <stack>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define mst(a,b) memset(a,b,sizeof(a))
const int MAX_ = 10;
const int MAX = 0x7fffffff;
int price[MAX_*11], score[MAX_*11], real[MAX_*11];
int dp[MAX_][MAX_*11][MAX_*11];
int main() {
int T;
int m, k, n, v1,v2;
while(~scanf("%d%d%d%d",&n,&v1,&v2,&k)) {
for(int i = 1; i <= n; ++i) {
scanf("%d%d%d",&price[i],&score[i],&real[i]);
}
mst(dp,0);
for(int i = 1; i <= n; ++i) {
for(int t = k; t > -1; --t) {
for(int j = v1; j > -1; --j) {
for(int r = v2; r > -1; --r) {
int maxm = 0;
if(t > 0){
maxm = max(dp[t-1][j][r] + real[i],maxm);
}
if(j >= price[i]){
maxm = max(dp[t][j - price[i]][r] + real[i],maxm);
}
if(r >= score[i]){
maxm = max(maxm,dp[t][j][r - score[i]] + real[i]);
}
dp[t][j][r] = max(maxm,dp[t][j][r]);
}
}
}
}
printf("%d\n",dp[k][v1][v2]);
}
return 0;
}