比賽的時候想出了DP的遞推式,感覺好像可以做但又不自信,後來又想錯了dp[i][j],第二維其實只有200多。(又急着走結果就否定掉自己思路了)
遞推式類似dp1[i][j] = max (dp2[i-j][j],dp2[i-j][j-1]) + pre[i]-pre[j]這樣,dp2同理,因爲是第一個人先動,所以最後會是dp1的最優值。但是這道題內存卡的小,看了網上大神的題解,有通過指針,還有滾動數組的做法,於是順便學了個新姿勢。
#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
using namespace std;
typedef long long ll;
#define maxn 20010
const int maxn2 = 255+10;
int dp[2][maxn2][205];
int v[maxn];
#define MOD 255
int pre[maxn];
int main()
{
int t;
int i;
int n;
scanf ("%d",&t);
while (t--){
memset (dp,0,sizeof(dp));
scanf ("%d",&n);
for (i=1;i<=n;i++){
scanf ("%d",&v[i]);
pre[i]=pre[i-1]+v[i] ;
}
int k = sqrt(2.0*n)+1;
int j;
for (i=n;i;i--)
for (j=k;j;j--){
if (i+j<=n){
dp[0][i&MOD][j]=pre[i+j-1]-pre[i-1]+max(dp[1][(i+j+1)&MOD][j+1]+v[i+j],dp[1][(i+j)&MOD][j]);
dp[1][i&MOD][j]=pre[i-1]-pre[i+j-1]+min(dp[0][(i+j+1)&MOD][j+1]-v[i+j],dp[0][(i+j)&MOD][j]);
}
else if (i+j-1<=n){
dp[0][i&MOD][j]=pre[i+j-1]-pre[i-1]+dp[1][(i+j)&MOD][j];
dp[1][i&MOD][j]=-pre[i+j-1]+pre[i-1]+dp[0][(i+j)&MOD][j];
}
}
printf("%d\n", dp[0][1][1]);
}
return 0;
}