codevs——2853 方格游戏(棋盘DP)

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 钻石 Diamond

题解

题目描述 Description

菜菜看到了一个游戏,叫做方格游戏~

游戏规则是这样的:

在一个n*n的格子中,在每个1*1的格子里都能获得一定数量的积分奖励,记左上角为(1,1),右下角为(n,n)。游戏者需要选择一条(1,1)到(n,n)的路径,并获得路径上奖励的积分。对于路径当然也有要求啦,要求是只能往坐标变大的方向走【从(x,y)到(x+1,y)或者(x,y+1)】,走过2n-1个区域到达(n,n)。当然,获得的积分最高的就能取胜啦。

这时,菜菜看到了他的好友月月,于是邀请她来玩双人版的。双人版的规则就是在单人版的基础上加上一条两人的路线不能相同。月月知道菜菜的很聪明,怕输得太惨,就不太愿意和他玩。菜菜可慌了,于是定义了一个公平值D,这个公平值等于俩人所选择的路径所能获得的积分一一对应相减的差的绝对值之和,即D=sigma (|kxi-kyi|)|(kx,ky分别为菜菜,月月走过的每一个区域的丛林系数)。不过这可是个庞大的计算任务,菜菜找到了你,请你帮忙计算公平值的最大值。

输入描述 Input Description

第一行,一个正整数n

接下来的n行,每行n个整数,表示丛林中每个区域的公平值

输出描述 Output Description

一个整数Dmax,即公平值的最大值

样例输入 Sample Input

4

1 2 3 4

1 5 3 2

8 1 3 4

3 2 1 5

样例输出 Sample Output

13

数据范围及提示 Data Size & Hint

对于20%的数据,保证0<n≤20

对于50%的数据,保证0<n≤50

对于100%的数据,保证0<n≤100且对于所有的i,j保证|Kij|≤300

分类标签 Tags 点此展开

动态规划 棋盘型DP

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n,a[200][200],dp[200][200][400];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>a[i][j];
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int k=1;k<=2*n;k++)
                dp[i][j][k]=-2147483640;
    dp[1][1][2]=0;
    for(int k=3;k<=2*n;k++){
        for(int j=1;j<=n;j++){
            for(int i=1;i<=n;i++){
                if(k-i>n || k-j>n) continue;
                if(k-i<1 || k-j<1) break;
                else dp[i][j][k]=max(max(dp[i-1][j][k-1],dp[i][j][k-1]),max(dp[i][j-1][k-1],dp[i-1][j-1][k-1]))+abs(a[i][k-i]-a[j][k-j]);
            }
        }
    }
    cout<<dp[n][n][2*n];
}

思路:

状态压缩,四维会爆!改成三维!

本题是一道典型的动态规划题。

我们首先来设计状态,用f[i][j][k]表示第i步时,菜菜的路径在横坐标为j的区域,月月的路径在横坐标为k的格子上时,当前公平值的最大值。这样三个值用来表示状态已经足够,因为菜菜和月月的位置可以用(j,i-j+1)和(k,i-k+1)来表示。

状态转移方程根据两人移动的方法设置如下:

f[i][j][k] = max{f[i-1][j-x][k-y]} + |a[j][i-j+1] - a[k][i-k+1]|,  x,y = 0,1}

这样,本题就解决了,本题的时间复杂度为O(n3)。

时间: 2024-12-19 08:04:10

codevs——2853 方格游戏(棋盘DP)的相关文章

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 }$

2853 方格游戏(三维棋盘)

时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 菜菜看到了一个游戏,叫做方格游戏~ 游戏规则是这样的: 在一个n*n的格子中,在每个1*1的格子里都能获得一定数量的积分奖励,记左上角为(1,1),右下角为(n,n).游戏者需要选择一条(1,1)到(n,n)的路径,并获得路径上奖励的积分.对于路径当然也有要求啦,要求是只能往坐标变大的方向走[从(x,y)到(x+1,y)或者(x,y+1)],走过2n-1个

codevs 2853:方格游戏

(排版没搞好,这一行用来卖萌~) 题目描述 Description 菜菜看到了一个游戏,叫做方格游戏~ 游戏规则是这样的: 在一个n*n的格子中,在每个1*1的格子里都能获得一定数量的积分奖励,记左上角为(1,1),右下角为(n,n).游戏者需要选择一条(1,1)到(n,n)的路径,并获得路径上奖励的积分.对于路径当然也有要求啦,要求是只能往坐标变大的方向走[从(x,y)到(x+1,y)或者(x,y+1)],走过2n-1个区域到达(n,n).当然,获得的积分最高的就能取胜啦. 这时,菜菜看到了他

codevs 1512 转向游戏 题解

Codevs 1512转向游戏 题解 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 白银 Silver 题解 题目描述 Description 小明自认为方向感很好,请小红来测试.小红先让小明面对北方立正站好,然后发出"向左转""向右转"或"向后转"的命令.每个命令执行后,小明都正确地说出了他面对的方向.小红的命令共N个(1≤n≤10000),请你统计小明说[南]的次数. 命令是以数字方式表达: 0---向左转 1---向右转 2

BZOJ 1413 取石子游戏(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1413 题意:n堆石子排成一排.每次只能在两侧的两堆中选择一堆拿.至少拿一个.谁不能操作谁输. 思路:参考这里. int f1[N][N],f2[N][N],n,a[N]; void deal() { RD(n); int i,j,k; FOR1(i,n) RD(a[i]),f1[i][i]=f2[i][i]=a[i]; int p,q,x; for(k=2;k<=n;k++) for(

求次短路 codevs 1269 匈牙利游戏

codevs 1269 匈牙利游戏 2012年CCC加拿大高中生信息学奥赛 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Welcome to the Hungary Games! The streets of Budapest form a twisted network of one-way streets. 欢迎来到匈牙利游戏!布达佩斯(匈牙利首都)的街道形成了一个弯曲的单向网络. You have been fo

BZOJ 1978 取数游戏(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1978 题意:给出一个数列a,在其中找出下标依次增大的数,使得任意相邻的两个数的最大公约数大于等于m.找出最多的数字. 思路:f[i]表示前面的数字中最大公约数为i可以找出的最多的数字个数.那么对于当前数字x: 接着更新f: int f[N],a[N]; int n,m; int main() { RD(n,m); int i; FOR1(i,n) RD(a[i]); int j,k;

炮(棋盘DP)

一直以为自己写的就是状态压缩,结果写完才知道是个棋盘dp 首先看一下题目 嗯,象棋 ,还是只有炮的象棋 对于方案数有几种,我第一个考虑是dfs,但是超时稳稳的,所以果断放弃 然后记得以前有过和这个题差不多的dp题 所以思路开始转向DP 经仔细思考后 将棋盘的状态压为三维 dp[i][k][j]; i:棋盘的第几行  k:前i行有几列放了一个炮棋  j:前i行有几列放了两个炮棋 因为炮会隔棋打,所以一列或者一行最多存在两个炮棋 所以 dp方程有6个元素: 1:不放炮棋,所以方程为 dp[i][k]

neu1458 方格取数 dp解法

题意: 有N * N个格子,每个格子里有正数或者0,从最左上角往最右下角走,只能向下和向右,一共走两次(即从左上角走到右下角走两趟),把所有经过的格子的数加起来,求最大值SUM,且两次如果经过同一个格子,则最后总和SUM中该格子的计数只加一次. 走两次,所以状态表示要同时表示两次路径.dp[i][j][k][l] 表示第一次走到i,  j,第二次走到k, l得到的最大值,这里i + j == k + l 其实第四维是可以通过前三维算出来的,所以可以去掉 那么dp[i][j][k] 可以通过四种状