zoukankan      html  css  js  c++  java
  • hdu4597 Play Game 区间DP

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

    全国邀请赛通化赛区第8题--题目重现

    思路:

    区间DP的思想,想法是队友想出来的,感觉很秒,自己处理的边界,果断AC

    边界处理很重要!!

    对于两列牌。我们定义f[x][y][k][h]表示对于当前状态中第一列牌处于区间(i,j),第二列牌处于区间(k,h)时,先手(即当前要选择牌的选手)和后手之间的最大差值

    定义sum1[x][y][k][h]表示先手的在此区间的获得的分数的最大值,sum2[x][y][k][h]表示后手在此区间的获得的分数的最大值

    那么如果对于当前的区间,当前的选手选择y位置的牌,那么f[x][y][k][h]=(sum1[x][y-1][k][h]+a[y]-sum2[x][y-1][k][h]);

    又很容易知道sum1[x][y-1][k][h]-sum2[x][y-1][k][h]=-f[x][y-1][k][h];

    为什么是负的呢??很简单,因为上一次的先手是对方啊

    同理,也可以选择x,k,h位置的牌

    那么我们最终可以得到这样一个简单的DP转移方程

    f[x][y][k][h]=max(-dfs(x,y-1,k,h)+a[y],-dfs(x+1,y,k,h)+a[x],-dfs(x,y,k+1,h)+b[k],-dfs(x,y,k,h-1)+b[h]);

    状态方程有了,实现的时候最重要的就是边界处理了。

    我用的是记忆化搜索的方式

    代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 #include<iostream>
     5 using namespace std;
     6 #define     N   22
     7 #define     INF 999999999
     8 int f[N][N][N][N], a[N], b[N], sum[2][N];
     9 bool vis[N][N][N][N];
    10 int n;
    11 int dfs(int i, int j, int k , int h)
    12 {
    13     int &x = f[i][j][k][h];
    14     if(vis[i][j][k][h]) return x;
    15     vis[i][j][k][h] = true;
    16     x=-INF;
    17     if(k==0&&h==0&&i==0&&j==0) return x=0;
    18     else
    19     if(k==0&&h==0 && i==j) return x=a[i];
    20     else
    21     if(i==0&&j==0 && k==h) return x=b[k];
    22     else
    23     if(k==0&&h==0) x=max(max(-dfs(i+1,j,0,0)+a[i],-dfs(i,j-1,0,0)+a[j]),x);
    24     else
    25     if(i==0&&j==0) x=max(max(-dfs(0,0,k+1,h)+b[k],-dfs(0,0,k,h-1)+b[h]),x);
    26     else 
    27     if(i==j && k!=h) x=max(max(max(-dfs(0,0,k,h)+a[i],-dfs(i,j,k+1,h)+b[k]),-dfs(i,j,k,h-1)+b[h]),x);
    28     else
    29     if(k==h && i!=j) x=max(max(max(-dfs(i,j,0,0)+b[k],-dfs(i+1,j,k,h)+a[i]),-dfs(i,j-1,k,h)+a[j]),x);
    30     else
    31     if(i==j&& k==h)  x=max(x,max(-dfs(0,0,k,h)+a[i],-dfs(i,j,0,0)+b[k]));
    32     else
    33     {   
    34         x= max(x, max(-dfs(i, j-1, k, h) + a[j], -dfs(i+1, j, k, h) + a[i]));
    35         x = max(x, max(-dfs(i, j, k, h-1) + b[h], -dfs(i, j, k+1, h) + b[k]));
    36     }
    37     
    38     return x;
    39 }
    40 int main()
    41 {
    42     int cases;
    43     scanf("%d", &cases);
    44     while(cases--) {
    45         scanf("%d", &n);
    46         int sum=0;
    47         for(int i = 1; i <= n; i++) scanf("%d", &a[i]),sum+=a[i];
    48         for(int i = 1; i <= n; i++) scanf("%d", &b[i]),sum+=b[i];
    49         memset(vis, false, sizeof(vis));
    50         int res = dfs(1, n, 1, n);
    51         cout<<(sum+res)/2<<endl;
    52     }
    53     return 0;
    54 }
    View Code
  • 相关阅读:
    刨析js代码执行机制
    H5离线缓存基础系列
    meta 详解
    如何成长为一名合格的web架构师?
    整理的互联网公司面试趋势
    http协议
    前端现在到底需要什么样的人才
    webpack 4.0 版本的简单使用
    vue的懒加载如何实现?
    Runtime的几个小例子(含Demo)
  • 原文地址:https://www.cnblogs.com/xiaozhuyang/p/hdu4597.html
Copyright © 2011-2022 走看看