zoj 2852 Deck of Cards扑克牌(三维dp)

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.

  • The game is played with a standard deck of 54 cards, namely A, 2, 3, 4, 5, 6 , 7, 8, 9, 10 (denoted as T), J, Q, K, Joker (denoted as F. However, the number of cards of a game may be up to 100.

  • In this game, an Ace values 1 point, the face cards (K, Q and J) value 10 points each and the remaining cards are valued by their numerical values. The joker is a bit different, which will be mentioned later.

  • There are 3 slots on the table, namely 1x, 2x, 3x.

  • A slot is available if the total points of the cards on that slot do not exceed 21.

  • The cards on a slot will be taken away as soon as the total points of cards are 21.

  • You are asked to put the cards on the table in the given order.

  • The cards can be put on a slot only if the slot is available.

  • A joker values as large as possible. In another word, a slot's total value becomes 21 immediately after placing a joker into it.

  • The game ends if no slot is available or the cards are all used.

  • You can get 50 dollars if you succeed putting one card onto the table, and 100 dollars multiplied by the number on the slot if you succeed eliminating cards on a slot.

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;
}


你可能感兴趣的:(zoj 2852 Deck of Cards扑克牌(三维dp))