题目链接: 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 的数目.
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }