hdu 4701 Game 博弈论

思路:

▶ 设 win(i,x,y) 表示当前可以买的物品是 i,先手有 x 元,后 手有 y 元时,先手是否必胜

▶ win(i,x,y) ⇐⇒∃j((j > i)∧(x ≥ si−sj)∧¬win(j,y,x−si +sj))

▶ 其中 si = Ci + Ci+1 +···+ CN

▶ 注意到 x + y = A + B−s1 + si,即 win(i,x) := win(i,x,y)

▶ win(i,x) =⇒ win(i,x + 1)

▶ 设 m(i) = min{x : win(i,x)},则 ¬win(i,x) ⇐⇒ x ≤ m(i)−1

▶ 令 D = A + B−s1 + si

▶           m(i) =min{x : ∃j((j > i)∧(x ≥ si −sj)∧¬win(j,D−x))}

          =min{x : ∃j((j > i)∧(x ≥ si −sj)∧D−x ≤ m(j)−1}

          =min{max{si −sj,D−m(j) + 1} : j > i}

          =min{max{si −sj,A + B−s1 + si −m(j) + +1} : j > i}

          =si + min{max{−sj,A + B−s1 −m(j) + 1} : j > i}

▶ 只要测试 A ≥ m(1)

代码如下:

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define ll __int64
#define M 1000002
#define inf 1e15
using namespace std;
int c[M];
ll s[M],m[M],cal,mi;
int main()
{
int n,q,i,a,mm,b,j;
while(scanf("%d%d%d",&n,&a,&b)!=EOF)
{
for(i=;i<n;i++) scanf("%d",&c[i]);
s[n]=;
for(i=n-;i>=;i--) s[i]=s[i+]+c[i];
m[n]=inf;mi=inf;
cal=a+b-s[]+;
for(i=n;i>=;i--){
mi=min(mi,max(-s[i],cal-m[i]));
m[i-]=s[i-]+mi;
}
puts(a>=m[]?"ALICE":"BOB");
}
return ;
}
上一篇:接口开发,tp5结合swagger-ui安装方法


下一篇:请求转发(forward)和重定向(redirect)的区别