Cogs 876. 游戏(DP)

  1. 游戏
    ★ 输入文件:game1.in 输出文件:game1.out 简单对比
    时间限制:1 s 内存限制:128 MB
    USACO/game1
    A Game游戏
    译 by 肖遥
    描述
    有如下一个双人游戏:N(2 <= N <= 100)个正整数的序列放在一个游戏平台上,游戏由玩家1开始,两人轮流从序列的两端取数,取数后该数字被去掉并累加到本玩家的得分中,当数取尽时,游戏结束。以最终得分多者为胜。
    编一个执行最优策略的程序,最优策略就是使玩家在与最好的对手对弈时,能得到的在当前情况下最大的可能的总分的策略。你的程序要始终为第二位玩家执行最优策略。
    格式
    PROGRAM NAME: game1
    INPUT FORMAT:
    (file game1.in)
    第一行: 正整数N, 表示序列中正整数的个数。
    第二行至末尾: 用空格分隔的N个正整数(大小为1-200)。
    OUTPUT FORMAT:
    (file game1.out)
    只有一行,用空格分隔的两个整数: 依次为玩家一和玩家二最终的得分。
    SAMPLE INPUT
    6
    4 7 2 9 5 2
    SAMPLE OUTPUT
    18 11
/*
贪心能骗60.
果然不对.
(没写错就是果然)
*/
#include<iostream>
#include<cstdio>
using namespace std;
int ansa,ansb,n;
int main()
{
    freopen("game1.in","r",stdin);
    freopen("game1.out","w",stdout);
    int x;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if(i&1) ansa+=x;
        else ansb+=x;
    }
    if(ansa<ansb) swap(ansa,ansb);
    printf("%d %d",ansa,ansb);
    return 0;
}
/*
区间DP.
f[i][j]表示[i,j] 1号取得的最大值.
然后看一下这个区间取哪个端点.
但是我们不能只关心端点.
因为要有两个人轮流取数.
对于一个区间[i,j] 
如果一个人先手取了i,那么他后手取了[i+1,j]区间
一个人先手取了j,那么他后手取了[i,j-1]区间
*/
#include<iostream>
#include<cstdio>
#define MAXN 101
using namespace std;
int n,f[MAXN][MAXN],sum[MAXN];
void slove()
{
    for(int i=n;i>=1;i--)
      for(int j=i+1;j<=n;j++) 
        f[i][j]=max(sum[j]-sum[i-1]-f[i+1][j],sum[j]-sum[i-1]-f[i][j-1]);
}
int main()
{
    freopen("game1.in","r",stdin);
    freopen("game1.out","w",stdout);
    int x;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        f[i][i]=x;
        sum[i]=sum[i-1]+x;
    }
    slove();
    printf("%d %d",f[1][n],sum[n]-f[1][n]);
    return 0;
}
原文地址:https://www.cnblogs.com/nancheng58/p/10068024.html