codevs 2853 方格游戏--棋盘dp

Posted rmy020718

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs 2853 方格游戏--棋盘dp相关的知识,希望对你有一定的参考价值。

方格游戏:http://codevs.cn/problem/2853/

 

这和传纸条和noip方格取数这两个题有一定的相似性,当第一眼看到的时候我们就会想到设计$dp[i][j][k][l]$(i,j表示一个人走到 i 行 j 个点,而另一个人走到 k 行第l个点)这么一个状态。

转移方程当然是$dp[i][j][k][l] = max{ dp[i-1][j][k-1][l] ,dp[i-1][j][k][l-1] ,dp[i][j-1][k-1][l] ,dp[i][j-1][k][l-1 }$。

这样设计没问题,只是空间限制不足,现在我们考虑进行优化。

注意题目中的一个限制条件,只能向右和向下走,那么每个人每次走到的点到出发点的曼哈顿距离相等。

曼哈顿距离:可以理解为 | 当前点的横坐标-出发点的横坐标 | + |当前点的纵坐标-出发点的纵坐标 | 。

有了曼哈顿距离,那么我们可以由每个点的横坐标表示出每个点的纵坐标,如此的话,我们设计状态的时候可以只设计每个人的横坐标加上曼哈顿距离这一状态。

那么这就是一个三维dp[i][j][k](i表示第一个人的横坐标,j表示的二个人的,k表示曼哈顿距离)。

说到如何继承无非有四种:

$dp[i][j][k] = max{ dp[i-1][j][k-1] ,dp[i][j-1][k-1] ,dp[i-1][j-1][k-1] ,dp[i][j][k-1] }$

不要忘记加上走到这个点获得的公平值。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,a[111][111];
int dp[111][111][222];
int max(int a,int b){ return a>b?a:b; }
int abs(int x){ return x<0?-x:x; } 
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&a[i][j]);
    for(int k=1;k<2*n;k++)
    {
        for(int i=1;i<=k&&i<=n;i++)
        {
            for(int j=1;j<=k&&j<=n;j++)
            {
                int s=max(max(dp[i-1][j][k-1],dp[i][j-1][k-1]),max(dp[i-1][j-1][k-1],dp[i][j][k-1]));
                dp[i][j][k]=s+abs(a[i][k-i+1]-a[j][k-j+1]);
            }
        }
    }
    printf("%d",dp[n][n][2*n-1]);
}

 

以上是关于codevs 2853 方格游戏--棋盘dp的主要内容,如果未能解决你的问题,请参考以下文章

「 CODE[VS] P2853 」 方格游戏

codevs 2853:方格游戏

2853 方格游戏(三维棋盘)

codevs1358棋盘游戏(状压dp)

Codevs1922骑士共存问题(最小割,二分图最大匹配)

[CodeVs1050]棋盘染色2(状态压缩DP)