USACO3.3.5--A Game

A Game
IOI'96 - Day 1

Consider the following two-player game played with a sequence of N positive integers (2 <= N <= 100) laid onto a game board. Player 1 starts the game. The players move alternately by selecting a number from either the left or the right end of the sequence. That number is then deleted from the board, and its value is added to the score of the player who selected it. A player wins if his sum is greater than his opponents.

Write a program that implements the optimal strategy. The optimal strategy yields maximum points when playing against the "best possible" opponent. Your program must further implement an optimal strategy for player 2.

PROGRAM NAME: game1

INPUT FORMAT

Line 1: N, the size of the board
Line 2-etc: N integers in the range (1..200) that are the contents of the game board, from left to right

SAMPLE INPUT (file game1.in)

6

4 7 2 9

5 2

OUTPUT FORMAT

Two space-separated integers on a line: the score of Player 1 followed by the score of Player 2.

SAMPLE OUTPUT (file game1.out)

18 11
题解:这个博弈问题可以用动态规划来解决。设sum[i]为序列s[1]...s[i]的和,f[i][j]表示先手玩家在序列i..j中获得的最大值。那么f[i][j]=sum[j]-sum[i-1]-min(f[i+1][j],f[i][j-1]),这个方程表示的是,如果先手玩家选取左边的元素s[i]或者右边的元素s[j],那么后手玩家肯定也会用最优策略选取f[i+1][j]或者f[i][j-1],我们只要使得后手玩家在序列i..j中获得的最大值最小即可。循环的时候注意i是从n递减的,因为我们要保证由飞f[i+1][j]和f[i][j-1]这两个子问题得出f[i][j]。(第一次提交的时候i是从1递增到n,果断WA了。。。以后记得认真考虑循环控制)。
View Code
 1 /*

 2 ID:spcjv51

 3 PROG:game1

 4 LANG:C

 5 */

 6 #include<stdio.h>

 7 #include<string.h>

 8 #define MAXSN 100

 9 long min(long a,long b)

10 {

11     return a<b?a:b;

12 }

13 int main(void)

14 {

15     freopen("game1.in","r",stdin);

16     freopen("game1.out","w",stdout);

17     long f[MAXSN+5][MAXSN+5],sum[MAXSN+5];

18     int s[MAXSN+5];

19     int i,j,n;

20     scanf("%d",&n);

21     sum[0]=0;

22     for(i=1; i<=n; i++)

23     {

24         scanf("%d",&s[i]);

25         sum[i]=sum[i-1]+s[i];

26         f[i][i]=s[i];

27     }

28     for(i=n; i>=1; i--)

29         for(j=i+1; j<=n; j++)

30             f[i][j]=sum[j]-sum[i-1]-min(f[i+1][j],f[i][j-1]);

31     printf("%ld %ld\n",f[1][n],sum[n]-f[1][n]);

32     return 0;

33 }

 



你可能感兴趣的:(USACO)