取数游戏
Description
简单的DP. 数据范围是突破口.
f[i][j][k][l] 表示在到达第(i + 2 * j + 3 * k + 4 * l)位分别使用i, j, k, l张牌时的最大得分. 对其进行维护即可.
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxN = 350;
int a[maxN];
int rec[5];
int f[42][42][42][42];
int main()
{
ios::sync_with_stdio(false);
int n, m;
cin >> n >> m;
for(int i = 0; i < n; i ++)
cin >> a[i];
for(int i = 0; i < m; i ++)
{
int x;
cin >> x;
rec[x]++;
}
memset(f, 0, sizeof(f));
for(int i = 0; i <= rec[1]; i ++)
for(int j = 0; j <= rec[2]; j ++)
for(int k = 0; k <= rec[3]; k ++)
for(int l = 0; l <= rec[4]; l ++)
{
f[i + 1][j][k][l] = max(f[i + 1][j][k][l],
f[i][j][k][l] + a[i + j * 2 + k * 3 + l * 4 + 1]);
f[i][j + 1][k][l] = max(f[i][j + 1][k][l],
f[i][j][k][l] + a[i + j * 2 + k * 3 + l * 4 + 2]);
f[i][j][k + 1][l] = max(f[i][j][k + 1][l],
f[i][j][k][l] + a[i + j * 2 + k * 3 + l * 4 + 3]);
f[i][j][k][l + 1] = max(f[i][j][k][l + 1],
f[i][j][k][l] + a[i + j * 2 + k * 3 + l * 4 + 4]);
}
cout << f[rec[1]][rec[2]][rec[3]][rec[4]] + a[0];
}