比赛的时候没仔细看题,感觉挺麻烦的就没写。赛后看了一下解题报告。。。其实这题不复杂,考虑出一种情况,剩下的Ctrl + C, Ctrl + V就行。
三维滚动数组。f[j][k][l]表示slot x1, x2, x3的值为j,k,l时的最优值。pre[j][k][l]表示他的前一个状态。
ps:发现一个trap。滚动数组f[][][]在给p[][][]传递完参数后要置0,否则影响下一次的运算。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int N = 25;
int f[N][N][N]; //f[x1][x2][x3]
int p[N][N][N];
int num(char c) {
if(c >= '2' && c <= '9') return c - '0';
if(c == 'A') return 1;
if(c == 'F') return -1;
else return 10;
}
int main() {
//freopen("data.in", "r", stdin);
int x, i, j, k;
int ans, l, n, t;
char c[2];
while(scanf("%d", &n), n) {
memset(f, 0, sizeof(f));
memset(p, 0, sizeof(p));
scanf("%s", c);
x = num(c[0]);
ans = 0;
if(x == -1) {
p[0][0][0] = 350;
ans = 350;
} else {
p[x][0][0] = 50;
p[0][x][0] = 50;
p[0][0][x] = 50;
ans = 50;
}
for(i = 2; i <= n; ++i) {
scanf("%s", c);
x = num(c[0]);
for(j = 0; j < 22; ++j) {
for(k = 0; k < 22; ++k) {
for(l = 0; l < 22; ++l) {
if(p[j][k][l] == 0) continue;
t = p[j][k][l];
//x1
if((x == -1 && j < 21) || x + j == 21) {
f[0][k][l] = max(f[0][k][l], t + 150);
} else if(x + j < 21) {
f[j+x][k][l] = max(f[x+j][k][l], t + 50);
} else if(x + j > 21 && j < 21) {
f[21][k][l] = max(f[21][k][l], t + 50);
}
//x2
if((x == -1 && k < 21) || x + k == 21) {
f[j][0][l] = max(f[j][0][l], t + 250);
} else if(x + k < 21) {
f[j][x+k][l] = max(f[j][x+k][l], t + 50);
} else if(x + k > 21 && k < 21) {
f[j][21][l] = max(f[j][21][l], t + 50);
}
//x3
if((x == -1 && l < 21) || x + l == 21) {
f[j][k][0] = max(f[j][k][0], t + 350);
} else if(x + l < 21) {
f[j][k][x+l] = max(f[j][k][x+l], t + 50);
} else if(x + l > 21 && l < 21) {
f[j][k][21] = max(f[j][k][21], t + 50);
}
}
}
}
for(j = 0; j < 22; ++j)
for(k = 0; k < 22; ++k)
for(l = 0; l < 22; ++l) {
p[j][k][l] = f[j][k][l];
ans = max(ans, p[j][k][l]);
f[j][k][l] = 0;
}
}
printf("%d\n", ans);
}
return 0;
}