2 1 23 53 3 10 100 20 2 4 3
53 105
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4597
题意:
给你两摞牌,每次可以任意一堆 的牌头或者牌尾抽牌。Alice先抽,Bob后抽,两个人都想抽到最多点数的牌。
做法:
dp[az][ay][bz][by]。 az,ay代表第一堆牌左边 和右边 分别抽到第几张了。然后在这个状态下 Bob抽到的点数。
因为dp表示的Bob的点数,所以牌堆里剩余奇数张牌的时候,是Bob抽,要取各种抽法的最大值。如果只剩偶数张牌,那么是Alice抽,要取 各种抽法中 的最小值。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <malloc.h> #include <ctype.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> using namespace std; #include <stack> #include <queue> #include <vector> #include <deque> #include <set> #include <map> int dp[30][30][30][30]; int a[30]; int b[30]; int dfs(int az,int ay,int bz,int by)//总数是偶数 { if(dp[az][ay][bz][by]!=-1) return dp[az][ay][bz][by]; int sum=ay-az+by-bz+2; int ans; if(sum&1) ans=0; else ans=9999999; if(sum==0) return dp[0][0][0][0]=0; if(az<=ay) { if(sum%2==1)//bob 取 { ans=max(dfs(az+1,ay,bz,by)+a[az],ans); ans=max(dfs(az,ay-1,bz,by)+a[ay],ans); } else { ans=min(dfs(az+1,ay,bz,by),ans); ans=min(dfs(az,ay-1,bz,by),ans); } } if(bz<=by) { if(sum%2==1) { ans=max(dfs(az,ay,bz+1,by)+b[bz],ans); ans=max(dfs(az,ay,bz,by-1)+b[by],ans); } else { ans=min(dfs(az,ay,bz+1,by),ans); ans=min(dfs(az,ay,bz,by-1),ans); } } return dp[az][ay][bz][by]=ans; } int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); memset(dp,-1,sizeof dp); a[0]=a[n+1]=b[0]=b[n+1]=0; int sum=0; for(int i=0;i<n;i++) { scanf("%d",&a[i+1]); sum+=a[i+1]; } for(int i=0;i<n;i++) { scanf("%d",&b[i+1]); sum+=b[i+1]; } printf("%d\n",sum-dfs(1,n,1,n)); } return 0; }