博弈DP太喵了qwq
设f[i][j]表示剩下区间【i,j】要取,先手最大值
明显我们要从这区间里面拿个最大的
就等价于这段区间的前缀和,我们要给对手留下个最小的
就是f[i][j]=sum[i][j]-min(f[i+1][j],f[i+2][j]......f[j][j],f[i][j-1].....f[i][i])
搞一搞优化可以O(n^2)做
#include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<algorithm> #define maxn 1020 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int d[maxn][maxn]; int w[maxn][maxn]; int f[maxn][maxn]; int sum[maxn]; int main(){ int T=read(); int inf=0x7fffffff; while(T--){ int n=read(); for(int i=1;i<=n;++i) sum[i]=read()+sum[i-1]; for(int len=1;len<=n;++len) for(int i=1;i+len-1<=n;++i){ int j=i+len-1; d[i][j]=w[i][j]=inf; f[i][j]=sum[j]-sum[i-1]-min(min(d[i][j-1],w[i+1][j]),0); if(i==j) d[i][j]=w[i][j]=sum[j]-sum[j-1]; else{ d[i][j]=min(d[i][j-1],f[i][j]); w[i][j]=min(w[i+1][j],f[i][j]); } } printf("%d ",f[1][n]); } return 0; }