hdu4597(区间DP)

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

区间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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#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到b2

int 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;
}


你可能感兴趣的:(acm之DP)