HDU - 2159 FATE(二维dp之01背包问题)

题目: 

 

思路: 二维dp,完全背包,状态转移方程dp[i][z] = max(dp[i][z], dp[i-1][z-a[j]]+b[j]),dp[i][z]表示在杀i个怪,消耗z个容忍度的情况下获得的最大的经验值。

刚看到这个题一直把思维限制在一维dp中,总是不能表达全部的条件,然后想到二维dp。因为目的是升级,所以dp表示的就要是最大的经验,下标自然就是剩下的条件忍耐度和杀怪的个数了。理清了这些,却死在设计程序上,,,,,,,,,终归是dp做的太少了。

代码:

 1 #include <iostream>
 2 #include <queue>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <cstring>
 7 #include <queue>
 8 #include <map>
 9 #include <vector>
10 #define INF 0x3f3f3f3f
11 #define FRE() freopen("in.txt","r",stdin)
12 
13 using namespace std;
14 typedef long long ll;
15 const int maxn = 500;
16 int n,m,k,s;
17 int dp[maxn][maxn],a[maxn],b[maxn];
18 int main()
19 {
20     ios::sync_with_stdio(false);
21     while(cin>>n>>m>>k>>s)
22     {
23         memset(dp,0,sizeof(dp));
24         for(int i=0; i<k; i++)
25             cin>>a[i]>>b[i];
26         for(int i = 1; i<=s; i++)//杀怪的个数
27         {
28             for(int j = 0; j<k; j++)//怪的种类
29             {
30                 for(int z = b[j]; z<=m; z++)//忍耐度
31                 {
32                     dp[i][z] = max(dp[i][z],dp[i-1][z-b[j]]+a[j]);//没选当前的这种怪就是dp[i][z]
33                 }                                                 //选了当前的这种怪就是dp[i-1][z-b[j]]+a[j]
34             }                                                     //因为当前的状态是由在一个状态的基础上转变来的
35         }
36         int ans = -1;
37         bool ok = true;
38         for(int i = 0; i<=m; i++)
39         {
40             if(dp[s][i]>=n)
41             {
42                 ans = m-i;
43                 break;
44             }
45         }
46         cout<<ans<<endl;
47     }
48     return 0;
49 }
50 /*
51 样例输入:
52 10 10 1 10
53 1 1
54 10 10 1 9
55 1 1
56 9 10 2 10
57 1 1
58 2 2
59 样例输出:
60 0
61 -1
62 1
63 */
View Code

 

posted @ 2018-10-02 19:46  sykline  阅读(214)  评论(0编辑  收藏  举报