題目大意
n堆石子,AB兩個人分別從兩頭開始取,每次取1~個數個,不能操作者輸
n,t<=100
題解
好題
首先AB兩人每次要麼取一個,要麼全部取完
題解並沒有詳細說明,這裏感性證一下
如果某一方對應的那堆石子大於其餘的之和,那麼其必勝,否則他會棄掉這堆去搶後面的
但是如果直接棄掉的話可能會輸,所以要先一個個拿來拖對面的時間,等到時機到了就直接全部丟掉
那麼有dp設f[i,j,k]表示[i,j]內A先手,第i堆是k是否能獲勝
發現當x能獲勝時,y>=x的y也能獲勝,所以改成f[i,j]表示最小獲勝的a[i],g[i,j]反之
考慮A的策略,假設求的是f[i,j]
A一開始會一個個的丟,B爲了讓A剩下儘量少的也會一個個丟,直到a[j]等於g[i+1,j]時,如果這時B繼續丟,那麼A可以直接丟掉a[i]然後B就輸了
所以B會在a[j]=g[i+1,j]的時候丟掉a[j],然後變成f[i,j-1]的情況,如果這時a[i]>=f[i,j-1]就可以贏
列出式子即可直接求,時間O(Tn^2)
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
//#define file
using namespace std;
int a[101],f[101][101],g[101][101],T,n,i,j,k,l;
int main()
{
#ifdef file
freopen("d.in","r",stdin);
#endif
scanf("%d",&T);
for (;T;--T)
{
scanf("%d",&n);
fo(i,1,n) scanf("%d",&a[i]);
memset(f,127,sizeof(f));
memset(g,127,sizeof(g));
fo(i,1,n) f[i][i]=g[i][i]=1;
fo(l,2,n)
{
fo(i,1,n-l+1)
{
j=i+l-1;
if (g[i+1][j]>a[j]) f[i][j]=1;
else f[i][j]=min(a[i]+1,f[i][j-1]+(a[j]-g[i+1][j])+1);
if (f[i][j-1]>a[i]) g[i][j]=1;
else g[i][j]=min(a[j]+1,g[i+1][j]+(a[i]-f[i][j-1])+1);
}
}
printf(f[1][n]<=a[1]?"First\n":"Second\n");
}
fclose(stdin);
fclose(stdout);
return 0;
}