http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1852
#include < iostream >
using   namespace  std;
int  dp[ 201 ][ 22 ][ 22 ][ 22 ];
// dp[k][r][s][t]表示前k张card里面三堆分别为r点、s点、t点时的最优值
int  MAX( int  x, int  y)
{
    
if( x>y )
        
return x;
    
else
        
return y;
}

int  fun( char  ch)
{
    
if(ch>='2' && ch<='9')
        
return ch-'0';
    
if(ch == 'A')
        
return 1;
    
if(ch == 'F')
        
return 11;
    
return 10;
}

int  main()
{
    
int n,k,r,s,t,maxs,m;
    
while(cin>>&& n)
    
{
        
char a;        
        
for(k=1;k<=n;k++)
            
for(r=0;r<22;r++)
                
for(s=0;s<22;s++)
                    
for(t=0;t<22;t++)
                        dp[k][r][s][t] 
= 0;
        cin
>>a;
        m 
= fun(a);
        
if(m == 11)
        
{
            dp[
1][0][0][0= 350;
        }

        
else
        
{
            dp[
1][m][0][0= 50;
            dp[
1][0][m][0= 50;
            dp[
1][0][0][m] = 50;
        }

        
for(k=2;k<=n;k++)
        
{
            cin
>>a;
             m 
= fun(a);
            
for(r=0;r<=21;r++)
                
for(s=0;s<=21;s++)
                    
for(t=0;t<=21;t++)
                    
{
                        
if(dp[k-1][r][s][t] == 0)
                            
continue;
                        
if(r + m == 21 || (m == 11 && r < 21 ))//一定要放在前面
                        {                 //r<21 表示还未超过21点
                            
//只有能放的情况下才能操作,s,t可以等于21
                            dp[k][0][s][t] = MAX(dp[k][0][s][t],dp[k-1][r][s][t] + 150);
                        }

                        
else if(r + m < 21)
                        
{
                            dp[k][r
+m][s][t] = MAX(dp[k][r+m][s][t],dp[k-1][r][s][t] + 50);
                        }

                        
else if(r + m > 21 && r < 21)
                        
{
                            dp[k][
21][s][t] = MAX(dp[k][21][s][t],dp[k-1][r][s][t] + 50);
                        }


                        
if(s + m == 21 || (m == 11 && s < 21))//一定要放在前面
                        {
                            dp[k][r][
0][t] = MAX(dp[k][r][0][t],dp[k-1][r][s][t] + 250);
                        }

                        
else if(s + m < 21)
                        
{
                            dp[k][r][s
+m][t] = MAX(dp[k][r][s+m][t],dp[k-1][r][s][t] + 50);
                        }

                        
else if(s + m > 21 && s < 21)
                        
{
                            dp[k][r][
21][t] = MAX(dp[k][r][21][t],dp[k-1][r][s][t] + 50);
                        }


                        
if(t + m == 21 || (m == 11 && t < 21))//一定要放在前面
                        {
                            dp[k][r][s][
0= MAX(dp[k][r][s][0],dp[k-1][r][s][t] + 350);
                        }

                        
else if(t + m < 21)
                        
{
                            dp[k][r][s][t
+m] = MAX(dp[k][r][s][t+m],dp[k-1][r][s][t] + 50);
                        }

                        
else if(t + m > 21 && t < 21)
                        
{
                            dp[k][r][s][
21= MAX(dp[k][r][s][21],dp[k-1][r][s][t] + 50);
                        }

                    }

        }

        maxs 
= 0;
        
for(k=1;k<=n;k++)
            
for(r=0;r<22;r++)
                
for(s=0;s<22;s++)
                    
for(t=0;t<22;t++)
                        
if(maxs < dp[k][r][s][t])
                            maxs 
= dp[k][r][s][t];
        cout
<<maxs<<endl;
    }

    
return 0;
}