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做的太少了。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 */