P2734 [USACO3.3]游戏 A Game——区间dp+博弈论

Description

  有如下一个双人游戏:N个正整数的序列放在一个游戏平台上,游戏由玩家1开始,两人轮流从序列的任意一端取一个数,取数后该数字被去掉并累加到本玩家的得分中,当数取尽时,游戏结束。以最终得分多者为胜。编一个执行最优策略的程序,最优策略就是使玩家在与最好的对手对弈时,能得到的在当前情况下最大的可能的总分的策略。你的程序要始终为第二位玩家执行最优策略。

Input

第一行: 正整数N, 表示序列中正整数的个数。

第二行至末尾: 用空格分隔的N个正整数(大小为1-200)。

Output

只有一行,用空格分隔的两个整数: 依次为玩家一和玩家二最终的得分。

Sample Input

6 
4 7 2 9 5 2

Sample Output

18 11

int

2 <= N <= 100

思路

计算型博弈论基础题。设\(f[l][r]\)为区间\([l,r]\)的先手取数的最大得分,

sum为前缀和,有状态转移方程:      

\(f[l][r]=max(s[r]-s[l-1]-f[l+1][r],s[r]-s[l-1]+f[l][r-1)=s[r]-s[l-1]-min(f[l+1][r],f[l][r-1])\)

注意到一个区间中的数要么被A区要么被B取,其总和不变,所以每个人的最优策略其实是让对手取最少的

数。

代码

#include<bits/stdc++.h>
#define maxn 105
using namespace std;
inline int read()
{
	int x=0;
	int f=1;
	char ch;
	ch=getchar();
	while(ch>'9'||ch<'0')
	{
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=x*10,x=x+ch-'0';
		ch=getchar();
	}
	return x*f;
} 


int n,sum[maxn],frog[maxn][maxn];

int main() {
    n=read();
    for(int i=1;i<=n;++i)
	{
        frog[i][i]=read();
		sum[i]=sum[i-1]+frog[i][i];
    }
    for(int i=1;i<=n;++i) {
        for(int l=1;l<=n;++l) {
            int r=l+i;
			if(r>n)    break;
            int s=sum[r]-sum[l-1];
            frog[l][r]=max(s-frog[l+1][r],s-frog[l][r-1]);//s是从l到r的区间和,选择第l个数,选择第r个数
        }
    }
    printf("%d %d\n",frog[1][n],sum[n]-frog[1][n]);
    return 0;
}
posted @ 2020-11-14 22:15  邦的轩辕  阅读(69)  评论(0编辑  收藏  举报