HDU 4597 Play Game (Interval DP (Memoized Search))

Topic link: http://acm.hdu.edu.cn/showproblem.php?pid=4597

Topic meaning:

There are two rows of cards, each with its own weight.

Two people take turns taking cards, and can only take cards from the left or right end of any row at a time.

Assuming that both of them are smart enough, find the maximum sum of weights that the first mover can get.

Problem solving ideas:

This question is classified as an interval DP. Let dp[l1][r1][l2][r2] mean that when the cards in the first row [l1, r1] and the second row [l2, r2] are taken, the first mover can get the maximum weight.

Then there are only four intervals associated with (l1, r1, l2, r2):

(l1+1,r1,l2,r2)

(l1,r1-1,l2,r2)

(l1,r1,l2+1,r2)

(l1,r1,l2,r2-1)

Then the state transition equation is:

dp[l1][r1][l2][r2]=max(dp[l1][r1][l2][r2],sum-solve(l1+1,r1,l2,r2)),(l1<=r1)
dp[l1][r1][l2][r2]=max(dp[l1][r1][l2][r2],sum-solve(l1,r1-1,l2,r2)),(l1<=r1)

dp[l1][r1][l2][r2]=max(dp[l1][r1][l2][r2],sum-solve(l1,r1,l2+1,r2)),(l2<=r2)
dp[l1][r1][l2][r2]=max(dp[l1][r1][l2][r2],sum-solve(l1,r1,l2,r2-1)),(l2<=r2)

where sum is the sum of the card weights in the first row [l1, r1] and the second row [l2, r2],

Pushing from the sub-interval is equivalent to a change in the order of successive moves, so the optimal solution of sum-sub-interval is equivalent to inversion, that is, the original operation of the first move becomes the second move, and the second move becomes the first move.

So why do we push it from the optimal sub-interval solution? Wouldn't it become a better solution for the second hand, and less weights for the first hand? Because the title says that the two are smart enough to choose the optimal solution.

Code:

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cctype>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #include<set>
10 #include<map>
11 #include<stack>
12 #include<string>
13 #define lc(a) (a<<1)
14 #define rc(a) (a<<1|1)
15 #define MID(a,b) ((a+b)>>1)
16 #define fin(name)  freopen(name,"r1",stdin)
17 #define fout(name) freopen(name,"w",stdout)
18 #define clr(arr,val) memset(arr,val,sizeof(arr))
19 #define _for(i,start,end) for(int i=start;i<=end;i++)  
20 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
21 using namespace std;
22 typedef long long LL;
23 const int N=25;
24 const int INF=0x3f3f3f3f;
25 const double eps=1e-10;
26 
27 int a[N],b[N];
28 int dp[N][N][N][N];
29 
30 int solve(int l1,int r1,int l2,int r2){
31     if(dp[l1][r1][l2][r2]!=-1)
32         return dp[l1][r1][l2][r2];
33         
34     int ans=0,sum=0;
35     if(l1<=r1)
36         sum+=a[r1]-a[l1-1]; 
37     if(l2<=r2)
 38          sum+=b[r2]-b[l2- 1 ];
 39      // Pushing from the sub-interval means that the order of the hands has changed, so using subtraction is equivalent to negating 
40      if (l1<= r1){
 41          ans=max(ans,sum-solve(l1+ 1 ,r1,l2,r2));
 42          ans=max(ans,sum-solve(l1,r1- 1 ,l2,r2));
 43      }
 44      if ( l2<= r2){
 45          ans=max(ans,sum-solve(l1,r1,l2+ 1 ,r2));
 46          ans=max(ans,sum-solve(l1,r1,l2,r2- 1 )) ;
 47      }
 48      
49      return dp[l1][r1][l2][r2]=ans;
50 }
51 
52 int main(){
53     FAST_IO;
54     int t;
55     scanf("%d",&t);
56     while(t--){
57         memset(dp,-1,sizeof(dp));
58         int n;
59         scanf("%d",&n);
60         _for(i,1,n){
61             cin>>a[i];
62             a[i]+=a[i-1];
63         }
64         _for(i,1,n){
65             cin>>b[i];
66             b[i]+=b[i-1];
67         }
68         printf("%d\n",solve(1,n,1,n));
69     }
70     return 0;
71 }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324652415&siteId=291194637