codevs1068(dp)

题目链接: http://codevs.cn/problem/1068/

题意: 中文题诶~

思路: dp

用 dp[i][j][k][l] 表示取 i 个 1, j 个 2, k 个 3, l 个 4 时最大贡献为多少, 那么初始化为 dp[0][0][0][0] = v[1], 其中 v[i] 表示 i 这点的权值. 动态转移方程式为:

1 int dis = i + 2 * j + 3 * k + 4 * l + 1;
2 if(i) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i - 1][j][k][l] + v[dis]);
3 if(j) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j - 1][k][l] + v[dis]);
4 if(k) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j][k - 1][l] + v[dis]);
5 if(l) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j][k][l - 1] + v[dis]);        

那么答案为 dp[a[1]][a[2]][a[3]][a[4]] 其中 a[i] 为 i 的数目.

代码:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 const int MAXN = 360;
 5 int dp[50][50][50][50], a[5], v[MAXN];
 6 
 7 int main(void){
 8     int n, m, x;
 9     cin >> n >> m;
10     for(int i = 1; i <= n; i++){
11         cin >> v[i];
12     }
13     for(int i = 1; i <= m; i++){
14         cin >> x;
15         a[x]++;
16     }
17     dp[0][0][0][0] = v[1];
18     for(int i = 0; i <= a[1]; i++){
19         for(int j = 0; j <= a[2]; j++){
20             for(int k = 0; k <= a[3]; k++){
21                 for(int l = 0; l <= a[4]; l++){
22                     int dis = i + 2 * j + 3 * k + 4 * l + 1;
23                     if(i) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i - 1][j][k][l] + v[dis]);
24                     if(j) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j - 1][k][l] + v[dis]);
25                     if(k) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j][k - 1][l] + v[dis]);
26                     if(l) dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j][k][l - 1] + v[dis]);
27                 }
28             }
29         }
30     }
31     cout << dp[a[1]][a[2]][a[3]][a[4]] << endl;
32     return 0;
33 }
View Code
原文地址:https://www.cnblogs.com/geloutingyu/p/7376428.html