USACO 3.4 A Game

来源:互联网 发布:plc伺服编程实例 编辑:程序博客网 时间:2024/05/30 05:15

http://ace.delos.com/usacoprob2?a=5yeP9Cco705&S=game1

题意:有一个两个人的游戏,游戏的规则是这样的:给你一个有N个数的数列,每次有一个选择这样数列的一端将该数删除,所得的分数就是该是的值,游戏从P1开始,问假设两个人都采用最优策略,最后两个人的得分是多少。

思路:博弈问题,可以用动态规划解决。状态为:dp[i][j][0] : 表示将[ i , j ]区间内的数删除,从P2开始P2最多能得的分数,dp[i][j][1]:表示将[ i , j ]区间内的数删除,游戏从P1开始,P2最多能得的分数。

状态转移方程为: dp[ i ] [ j ] [ 0 ] = MAX( dp[ i+1 ] [ j ] [ 1 ] + num [ i ]  , dp[ i ] [ j -1 ] [ 1 ] + num [ j ] );

dp[ i ] [ j ] [ 1 ]  = MIN( dp[ i ] [ j ] [ 0]  , dp[ i ] [ j ] [ 0 ] ) ;  //这里是MIN是因为两者都采取最优的策略。

代码:

/*ID : chrisLANG :C++TASK : game1*/#include<stdio.h>#include<string.h>#define MAX(a,b) (a)>(b)?(a):(b)#define MIN(a,b) (a)>(b)?(b):(a) int dp[210][210][2] ;int N ,sum;int num[210] ;void DP(){memset(dp , 0 ,sizeof(dp) );for(int i=1;i<=N;i++){dp[i][i][0] = num[i] ;dp[i][i][1] = 0 ;}for(int len=2;len<=N;len++){for(int i=1;i+len<=N+1;i++){int j = i + len - 1;dp[i][j][0] = MAX( dp[i+1][j][1] + num[i] , dp[i][j-1][1] + num[j] );dp[i][j][1] = MIN( dp[i+1][j][0] , dp[i][j-1][0] );}}printf("%d %d\n",sum-dp[1][N][1],dp[1][N][1]);}int main(){freopen("game1.in","r",stdin);freopen("game1.out","w",stdout);while(scanf("%d",&N) == 1){sum = 0 ;for(int i=1;i<=N;i++){scanf("%d",&num[i]);sum += num[i] ;}DP();}return 0; }