USACO 3.3 A Game

USACO 3.3 A Game


动态规划法。
用dp[player][start][end]表示player在[start..end]会取得的最大值。
如果player==0,那么player有主动权,它要么选start,要么选end.显然,它要选使得对手得分最少的那一个。
当它选start时,对手所能到的最大值为dp[1][start+1][end]。当它选end时,对手所选的最大值是dp[1][start][end-1].
。所以我们选dp[1][start+1][end]和dp[1][start][end-1]中小的那一个。
如果player==1,那只能被动的等0先选了。1在剩下区段中,又作为先选的角色,即player0。
当只有一个数字的时候,player0就只有选这个,player1就没得选,返回0.
代码如下:

#include  < iostream >
#include 
< fstream >

using   namespace  std;

ifstream fin(
" game1.in " );
ofstream fout(
" game1.out " );

#ifdef _DEBUG
#define  out cout
#define  in cin
#else
#define  out fout
#define  in fin
#endif

int  dp[ 2 ][ 100 ][ 100 ];
int  sequence[ 100 ];

int  score( int  player, int  start, int  end)
{
    
if (dp[player][start][end] !=- 1 )
        
return  dp[player][start][end];

    
if (start == end){
        
if (player == 0 )
            dp[player][start][end] 
=  sequence[start];
        
else  
            dp[player][start][end] 
=   0 ;
    }
else {
        
int  t1  =  score( 0 ,start + 1 ,end);
        
int  t2  =  score( 0 ,start,end - 1 );
        
if (player == 0 ){
            
if (t1 > t2){
                dp[player][start][end] 
=  sequence[end] + score( 1 ,start,end - 1 );
            }
else {
                dp[player][start][end] 
=  sequence[start] + score( 1 ,start + 1 ,end);
            }
        }
else {
            
if (t1 > t2){
                dp[player][start][end] 
=  score( 0 ,start,end - 1 );
            }
else {
                dp[player][start][end] 
=  score( 0 ,start + 1 ,end);
            }
        }
    }

    
return  dp[player][start][end];
}

void  solve()
{
    memset(dp,
- 1 , sizeof (dp));

    
int  size;
    
in >> size;

    
for ( int  i = 0 ;i < size; ++ i)
        
in >> sequence[i];

    
out << score( 0 , 0 ,size - 1 ) << "   " << score( 1 , 0 ,size - 1 ) << endl;
}

int  main( int  argc, char   * argv[])
{
    solve(); 
    
return   0 ;
}


你可能感兴趣的:(USACO 3.3 A Game)