Atcoder Grand Contest 048 (AGC048) D - Pocky Game 博弈,动态规划

原文链接www.cnblogs.com/zhouzhendong/AGC048D.html

前言

我居然更博了???

题解

结论1

对于任何一方来说,他当前要取的那堆的石子个数多多益善。

证明1

假设多了 \(k\) 个石子,那么对于在原先的石子堆中取石子的任意方案,只需要在第一步多取 \(k\),就对应到新石子堆的一个方案。由此可见新石子堆的决策集合包含了旧石子堆,所以必然不劣。

结论2

取石子时,只可能取走一个 或者 取走一堆。

证明2

假设没取完一堆,但是取走了大于一个,那不如取一个,因为取一个剩下的石子数较多,肯定不劣。


如果以事件"某一次某一方取走一堆"为双方最优决策序列的分隔点,那么我们会发现双方一直都在轮流取一个石子。

这启发我们使用动态规划解决这个问题。

\(vl(L,R)\) 表示保留 \([L,R]\) 范围的石子,如果左方先手,且在第 \(L\) 堆石子之前还有一堆大小为 \(x(x > 0)\) 的石子,那么 \(x\) 至少为多少才能保证先手必胜。

类似地,我们定义 \(vr(L,R)\),表示右方先手,在右侧至少有一堆多大的石子才能保证必胜。

两部分做法一样,所以这里我们不妨只考虑左方。

左方第一步有两种决策:拿光一堆、拿一个。

\(vr(L,R-1) > a[R]\) 时,显然直接拿光就赢了,所以此时 \(lv(L,R) = a[R]+1\)

否则肯定是双方轮流拿一个,直到某一方发现这一次如果拿光的话对方就输了。设左侧石子堆大小为 \(x\),则左方在拿走 \(x - vr(L,R-1) + 1\) 个石子后,右方拿一堆,右方获胜;或者右方在拿走 \(a[R] - vl(L,R-1) + 1\) 个石子后,左方拿一堆,左方获胜。所以左方获胜的条件是 \(x - vr(L,R-1) + 1 > a[R] - vl(L,R-1) + 1\),即 \(vr(L,R) = \min(x) = a[R] - vl(L,R-1) + vr(L,R-1) + 1\)

直接 DP 或者 记忆化 dfs 均可。

于是我们得到了一个单组数据 \(O(n^2)\) 的算法,解决了此题。

代码

#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof(x))
#define For(i,a,b) for (int i=(a);i<=(b);i++)
using namespace std;
typedef long long LL;
LL read(){
	LL x=0,f=0;
	char ch=getchar();
	while (!isdigit(ch))
		f=ch=='-',ch=getchar();
	while (isdigit(ch))
		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}
const int N=105;
int n;
int a[N];
LL l[N][N],r[N][N];
LL vr(int L,int R);
LL vl(int L,int R){
	if (L>R)
		return 1;
	LL &res=l[L][R];
	LL v=a[R];
	if (res)
		return res;
	LL b=vr(L,R-1);
	if (b>v)
		return res=1;
	LL a=vl(L,R-1);
	// x - a + 1 > v - b + 1
	return res=max(1LL,v-b+1+a-1+1);
}
LL vr(int L,int R){
	if (L>R)
		return 1;
	LL &res=r[L][R];
	LL v=a[L];
	if (res)
		return res;
	LL b=vl(L+1,R);
	if (b>v)
		return res=1;
	LL a=vr(L+1,R);
	// x - a + 1 > v - b + 1
	return res=max(1LL,v-b+1+a-1+1);
}
void solve(){
	n=read();
	For(i,1,n)
		a[i]=read();
	clr(l),clr(r);
	puts(vl(2,n)<=a[1]?"First":"Second");
}
int main(){
	int T=read();
	while (T--)
		solve();
	return 0;
}
posted @ 2020-10-18 22:40  zzd233  阅读(431)  评论(0编辑  收藏  举报