21-point is a small game played with cards. Its aim is to accumulate the points on the cards so as to get 21 points. This game also appears on some cell phones.
To simplify the problem, let's have some assumptions.
Now your task is to calculate the maximum money you can get.
Input
The input contains multiple test cases!
The first line contains an integer N, denoting the number of cards of this game. The next line contains N characters separated by a single space, denoting the cards.
A line with N = 0 signals the end of the input, which should not be processed.
Output
Output the maximum money you can get in one line for each test case.
Sample Input
1
F
10
J J J J J J J J J J
11
F T J Q K T J Q K T J
2
A A
0
Sample Output
350
450
800
100
Hint:
In the first case, you can put the joker onto the 3x slot and get 21 points. The total money you get is 50 + 100 * 3 = 350 dollars.
In the second case, you can only put 3 J's onto each slot and no slot is available then. The total money you get is 50 * 9 = 450 dollars.
The third case is a combination of the first two. Note that the first joker can't be counted as 1 point.
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1852
题目非常难理解,而且容易理解错。。。
答案还和输入的顺序有关系,比如TTATTATTATTAF 和 AAAATTTTTTTTF 一个1800,一个1100
#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> using namespace std; const int N = 25; int f[N][N][N]; //f[x1][x2][x3] 3个槽的数量 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() { 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是f的前一个状态(因为要考虑x1x2x3三种情况,不方便用一个数组) p[0][0][x] = 50; ans = 50; } for(i = 2; i <= n; ++i) { scanf("%s", c); x = num(c[0]); ////char和int之间的转换 for(j = 0; j < 22; ++j) { for(k = 0; k < 22; ++k) { //范围:1-20 0:刚好等于21 21:大于21 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) { //0表示刚好等于21时 。j等于21其时实这个容器已经大于21,所以不继续 f[0][k][l] = max(f[0][k][l], t + 150); } else if(x + j < 21&&x!=-1) { // 介于 0-20之间的正常数 f[j+x][k][l] = max(f[x+j][k][l], t + 50); } else if(x + j > 21 && j < 21) { //这时x肯定不可能是-1 f[21][k][l] = max(f[21][k][l], t + 50); //大于21的都归为21(妙,表明后续已经不能往里加了) } //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&&x!=-1) { 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&&x!=-1) { 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; // f数组清空 } } printf("%d\n", ans); } return 0; }