• HDU 4597 Play Game(区间DP(记忆化搜索))


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4597

    题目大意:

    有两行卡片,每个卡片都有各自的权值。

    两个人轮流取卡片,每次只能从任一行的左端或右端取卡片。

    假设两人都足够聪明,求先手能够取到的最大权值之和。

    解题思路:

    这题就归为区间DP吧,设dp[l1][r1][l2][r2]表示取完第一行[l1,r1]和第二行[l2,r2]的卡片时,先手能够获得的最大权值。

    那么跟(l1,r1,l2,r2)关联的区间只有四个:

    (l1+1,r1,l2,r2)

    (l1,r1-1,l2,r2)

    (l1,r1,l2+1,r2)

    (l1,r1,l2,r2-1)

    那么状态转移方程就为:

    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)

    其中sum为第一行[l1,r1]和第二行[l2,r2]卡片权值之和,

    从子区间推过来相当于先后手顺序发生了改变,所以sum-子区间最优解相当于取反,就是原来先手的操作变成后手,后手变成先手。

    那么我们为什么要从最优子区间解里推过来呢,那样不就变成了让后手有了较优解了吗,不就让先手获得的权值变少了吗?因为题目说了两人足够聪明,选取的都是最优解。

    代码:

     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     //从子区间推过来相当于先后手顺序发生了改变,所以用减相当于取反
    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
    ",solve(1,n,1,n));
    69     }
    70     return 0;
    71 }
  • 相关阅读:
    Spring xml中进行面向切面的配置
    Spring 基于Java的Bean声明
    Spring context:component-scan中使用context:include-filter和context:exclude-filter
    Spring context:component-scan代替context:annotation-config
    Spring 使用context:annotation-config的设置
    Spring xml中进行autowired的方式
    margin三个值
    Spring util-namespace下标签相关操作
    use strict 的优点
    Spring MVC整合DWR
  • 原文地址:https://www.cnblogs.com/fu3638/p/8909708.html
Copyright © 2020-2023  润新知