这道题还是去长春之前看的,当时以为是博弈什么的。后来学长说是记忆化搜索,当时连简单的DP都不会,只好先扔到一边了。
dp[s1][e1][s2][e2] 表示第一排剩[s1,e1] ,第二排剩 [s2,e2] 时的最优决策。
dp[s1][e1][s2][ e2 ] = sum - min(dfs(s1,e1,s2+1,e2),dfs(s1,e1,s2,e2-1),dfs(s1+1,e1,s2,e2),dfs(s1,e1-1,s2,e2))。注意边界。
sum表示当前状态下两排数的总和。
A取时,要保证B在下一回合的最优决策最小。既保证自己在这一回合的决策最优。
#include#include #include #include #include #include #include #include #pragma comment(linker, "/STACK:1024000000"); #define EPS (1e-6) #define LL long long #define ULL unsigned long long int #define _LL __int64 #define _INF 0x3f3f3f3f #define Mod 1000000007 using namespace std; int dp[22][22][22][22]; int num[3][21]; int ans[3][21]; int dfs(int s1,int e1,int s2,int e2) { if(s1 > e1 && s2 > e2) { return 0; } if(dp[s1][e1][s2][e2] != -1) return dp[s1][e1][s2][e2]; if(s1 > e1) { dp[s1][e1][s2][e2] = ans[2][e2] - ans[2][s2-1] - min(dfs(s1,e1,s2+1,e2),dfs(s1,e1,s2,e2-1)); } else if(s2 > e2) { dp[s1][e1][s2][e2] = ans[1][e1] - ans[1][s1-1] - min(dfs(s1+1,e1,s2,e2),dfs(s1,e1-1,s2,e2)); } else { int t1 = ans[2][e2] - ans[2][s2-1] + ans[1][e1] - ans[1][s1-1] - min(dfs(s1,e1,s2+1,e2),dfs(s1,e1,s2,e2-1)); int t2 = ans[2][e2] - ans[2][s2-1] + ans[1][e1] - ans[1][s1-1] - min(dfs(s1+1,e1,s2,e2),dfs(s1,e1-1,s2,e2)); dp[s1][e1][s2][e2] = max(t1,t2); } return dp[s1][e1][s2][e2]; } int main() { int T,n,i; scanf("%d",&T); while(T--) { scanf("%d",&n); for(i = 1;i <= n; ++i) { scanf("%d",&num[1][i]); } for(i = 1;i <= n; ++i) { scanf("%d",&num[2][i]); } ans[1][0] = 0; ans[2][0] = 0; for(i = 1;i <= n; ++i) { ans[1][i] = ans[1][i-1] + num[1][i]; ans[2][i] = ans[2][i-1] + num[2][i]; } memset(dp,-1,sizeof(dp)); dfs(1,n,1,n); printf("%d\n",dp[1][n][1][n]); } return 0; }