hdu4597(区间DP)

来源:互联网 发布:mysql替换部分字符串 编辑:程序博客网 时间:2024/05/20 16:33

这是区域赛的一道题目,感觉还是很难,做了好久都没想法,然后看了解题

区间dp,dp[a1][a2][b1][b2]表示在这两个区间内,先后所能获得的最大值,然后就是状态转移,有四种可能,以取a堆最左边的那个数字为例,状态转移方程如下:

dp[a1][a2][b1][b2] = max(dp[a1][a2][b1][b2],a[a1+1]+suma[a2-1]-suma[a1+1]+sumb[b2-1]-sumb[b1]-dfs(a1+1,a2,b1,b2));

数组的含义看代码注释,-法后手的东西表示后首在先手完成的情况下实现的最大价值

#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#include<time.h>#include<math.h>#define N 25#define inf 0x7fffffff#define eps 1e-9#define pi acos(-1.0)#define P system("pause")using namespace std;int a[N],b[N];//a,b记录输入数组int suma[N],sumb[N];//记录前i个数之后int dp[N][N][N][N];//第一堆代表区间a1到a2,第一堆b1到b2int dfs(int a1,int a2,int b1,int b2){    if(dp[a1][a2][b1][b2] != -1) return dp[a1][a2][b1][b2];    dp[a1][a2][b1][b2] = 0;    if(a1+1 < a2)        dp[a1][a2][b1][b2] = max(dp[a1][a2][b1][b2],a[a1+1]+suma[a2-1]-suma[a1+1]+sumb[b2-1]-sumb[b1]-dfs(a1+1,a2,b1,b2));    if(a1 < a2-1)        dp[a1][a2][b1][b2] = max(dp[a1][a2][b1][b2],a[a2-1]+suma[a2-2]-suma[a1]+sumb[b2-1]-sumb[b1]-dfs(a1,a2-1,b1,b2));    if(b1+1 < b2)        dp[a1][a2][b1][b2] = max(dp[a1][a2][b1][b2],b[b1+1]+suma[a2-1]-suma[a1]+sumb[b2-1]-sumb[b1+1]-dfs(a1,a2,b1+1,b2));    if(b1 < b2-1)        dp[a1][a2][b1][b2] = max(dp[a1][a2][b1][b2],b[b2-1]+suma[a2-1]-suma[a1]+sumb[b2-2]-sumb[b1]-dfs(a1,a2,b1,b2-1));    return dp[a1][a2][b1][b2];}int main(){//freopen("input.txt","r",stdin);//freopen("output.txt","w",stdout);    int t;    scanf("%d",&t);    while(t--)    {        int n;        scanf("%d",&n);        int i,j;        suma[0] = 0;        for(i = 1; i <= n; i++){            scanf("%d",&a[i]);            suma[i] = suma[i-1] + a[i];        }        sumb[0] = 0;        for(i = 1; i <= n; i++)        {            scanf("%d",&b[i]);            sumb[i] = sumb[i-1] + b[i];        }        memset(dp,-1,sizeof(dp));        dfs(0,n+1,0,n+1);        printf("%d\n",dp[0][n+1][0][n+1]);    }    return 0;}


0 0
原创粉丝点击