SRM 563 DIV1 DIV2

2、0-1背包问题,边界问题稍微麻烦一些。

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 #include <cstdlib>
 5 #include <map>
 6 #include <algorithm>
 7 #include <stack>
 8 #include <queue>
 9 #include <cmath>
10 using namespace std;
11 int dp[105][105];//dp[i][j],从第i个card开始,后边剩余j张牌的情况下最大的damage
12 class SpellCards {
13 public:
14     int maxDamage(vector<int> level, vector<int> damage) {
15         int dsz = damage.size();
16         int lsz = level.size();
17         int res = 0;
18 
19         for (int id = 0; id < dsz; id++) {
20             rotate(level.begin(), level.begin() + 1, level.end());
21             rotate(damage.begin(), damage.begin() + 1, damage.end());
22             memset(dp, -1, sizeof(dp));
23             
24             if (level[lsz - 1] == 1) {//初始化倒数第一个
25                 dp[lsz - 1][0] = damage[lsz - 1];
26             }
27             dp[lsz - 1][1] = 0;
28 
29             for (int i = lsz - 2; i > -1; i--) { //倒数第二个个位置开始
30                 for (int j = 0; j < lsz - i + 1; j++) {//后边还剩下j个可以用
31                     if (0 == j) { //初始化dp的值,表示不使用当前的card
32                         dp[i][j] = -1;
33                     } else {
34                         dp[i][j] = dp[i + 1][j - 1];
35                     }
36                     
37                     int use_need = level[i] - 1; //使用之后需要的个数
38                     if (dp[i + 1][j + use_need] != -1) {//如果可以使用
39                         dp[i][j] = max(dp[i][j],
40                                 dp[i + 1][j + use_need] + damage[i]);
41                         res = max(res, dp[i][j]);
42                     }
43                 }
44             }
45         }
46         return res;
47     }
48 };

 递归版本

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 #include <cstdlib>
 5 #include <map>
 6 #include <algorithm>
 7 #include <stack>
 8 #include <queue>
 9 #include <cmath>
10 using namespace std;
11 int dp[105][105];//dp[i][j],从第i个card开始,后边剩余j张牌的情况下最大的damage
12 class SpellCards {
13 public:
14     int rec(vector<int>& level, vector<int>& damage,int cur,int need,int total){
15         int &res=dp[cur][need];
16         if(-1==res){
17             if((cur+need)==total){
18                 res=0;
19             }else{
20                 res=rec(level,damage,cur+1,max(need-1,0),total);//不使用
21                 if((cur+need+level[cur])<=total){//使用
22                     res=max(res,damage[cur]+rec(level,damage,cur+1,need+level[cur]-1,total));
23                 }
24             }
25         }
26         return res;
27     }
28     int maxDamage(vector<int> level, vector<int> damage) {
29         int dsz = damage.size();
30         int lsz = level.size();
31         int res = 0;
32 
33         for (int id = 0; id < dsz; id++) {
34             rotate(level.begin(), level.begin() + 1, level.end());
35             rotate(damage.begin(), damage.begin() + 1, damage.end());
36             memset(dp, -1, sizeof(dp));
37             res = max(res, rec(level,damage,0,0,lsz));
38         }
39         return res;
40     }
41 };

 最高效方法:http://www.cppblog.com/hanfei19910905/archive/2012/12/09/196119.aspx

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 #include <cstdlib>
 5 #include <map>
 6 #include <algorithm>
 7 #include <stack>
 8 #include <queue>
 9 #include <cmath>
10 using namespace std;
11 int dp[55];
12 //dp[i]当前有i张牌的情况下的最大的damage
13 int work(vector<int> a, vector<int> d) {
14     int n = a.size(), ans = 0;
15     memset(dp, -1, sizeof(dp));
16     dp[0] = 0;
17     for (int j = n - 1; j > -1; j--) {
18         for (int i = n; i; i--)
19             if (i - a[j] >= 0) {
20                 int v = i - a[j];
21                 if (dp[v] == -1)
22                     continue;
23                 dp[i] = max(dp[i], dp[v] + d[j]);
24                 ans = max(ans, dp[i]);
25             }
26     }
27     return ans;
28 }
29 class SpellCards {
30 public:
31     int maxDamage(vector<int> level, vector<int> damage) {
32         return work(level, damage);
33     }
34 };

 

posted on 2012-12-15 16:16  kakamilan  阅读(194)  评论(0编辑  收藏  举报

导航