洛谷P2734 游戏 A Game

传送门

题目大意:从一个序列两端取数,先后手两人

均采用最优策略,问先后手的得分。

题解:

区间dp

如果先手面临的状态是a1,a2,a3,a4,a5.

如果取走一个那么后手面临的状态是a2,a3,a4,a5、

同样也是一个最优值。

f[l][r]表示选手A面临[l,r]状态的最优值,那么选手B的最优值

就是区间[l,r]的区间和-f[l][r].

记忆化搜索用结构体返回两个玩家的得分

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 220
using namespace std;

int n;

int a[N],sum[N],f[N][N];

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
     scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i],f[i][i]=a[i];
    for(int len=2;len<=n;len++){
        for(int l=1;l+len-1<=n;l++){
            int r=l+len-1;
            f[l][r]=max(sum[r]-sum[l-1]-f[l+1][r],sum[r]-sum[l-1]-f[l][r-1]);
        }
    }
    printf("%d %d",f[1][n],sum[n]-f[1][n]);
    return 0;
}
dp
#include<iostream>
#include<cstdio>
#include<cstring>
#define N  220
using namespace std;

int n;

int a[N],sum[N],dp[N][N];

struct Score{
    int p0,p1;
};

Score dfs(int l,int r,int p){
     if(l==r){
         if(p)return (Score){0,a[l]};
         return (Score){a[l],0};
     }
     if(dp[l][r]){
         if(p) return (Score){sum[r]-sum[l-1]-dp[l][r],dp[l][r]};
         return (Score){dp[l][r],sum[r]-sum[l-1]-dp[l][r]};
     }
     if(p){
         dp[l][r]=max(dfs(l+1,r,0).p1+a[l],dfs(l,r-1,0).p1+a[r]);
         return (Score){sum[r]-sum[l-1]-dp[l][r],dp[l][r]};
     }else{
         dp[l][r]=max(dfs(l+1,r,1).p0+a[l],dfs(l,r-1,1).p0+a[r]);
         return (Score){dp[l][r],sum[r]-sum[l-1]-dp[l][r]};
     }
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
    Score ans=dfs(1,n,0);
    printf("%d %d\n",ans.p0,ans.p1);
    return 0;
}
记忆化搜索

 

posted @ 2017-11-06 06:32  ANhour  阅读(299)  评论(0编辑  收藏  举报