A Game

来源:互联网 发布:带着淘宝混异世 编辑:程序博客网 时间:2024/05/14 09:46

题意:有一列N个正整数,两个玩家1和2,1先行动。每次决策中,行动的玩家可以从这个序列的最左边或者最右边将数取出,加到自己的分堆中。如果两人都选择自己的最优策略,求两个玩家最后的得分分别为多少?

解题思路

  1. 这是个很简单的DP问题,设这一列数用board[i] = j来表示,代表第i个数(从1到N计数)为j。f[i][j] = k代表游戏开始的时候序列为原序列的第i到第j个数,那么先走的玩家选择最优策略最后的得分是k。sum[i][j] = k代表 board[i] + board[i+1] + ... + board[j] = k。
  2. 边界条件,f[i][i] = board[i]
  3. 滚雪球的过程:f[i][j] = max{board[i] + sum[i + 1][j] - f[i + 1][j],   board[j] + sum[i][j - 1] - f[i][j - 1]}
  4. 直接用递归的话会超时,那么倒序进行滚雪球就可以变成一个非递归,详情见代码

代码

/*ID: zc.rene1LANG: CPROG: game1*/#include<stdio.h>#include<stdlib.h>#include<string.h>int board[101];int sum[101][101];int main(void){    FILE *fin, *fout;    int N;    int i, j, x, y;    int f[101][101];    fin = fopen("game1.in", "r");    fout = fopen("game1.out", "w");    /*get input*/    fscanf(fin, "%d", &N);    for (i=1; i<=N; i++)    {fscanf(fin, "%d", &board[i]);    }    /*get the sum result*/    for (i=1; i<=N; i++)    {for (j=1; j<=N; j++){    if (i == j)    {sum[i][j] = board[i];    }    else if (i < j)    {sum[i][j] = sum[i][j-1] + board[j];    }    else    {sum[i][j] = -1;    }}    }    /*begin DP*/    for (i=1; i<=N; i++)    {f[i][i] = board[i];    }    for (j=1; j<=(N-1); j++)    {for (i=1; (i+j)<=N; i++){    x = board[i] + sum[i+1][i+j] - f[i+1][i+j];    y = board[i+j] + sum[i][i+j-1] - f[i][i+j-1];    f[i][i+j] = (x > y) ? x : y;}    }    fprintf(fout, "%d %d\n", f[1][N], sum[1][N] - f[1][N]);    return 0;}



































原创粉丝点击