zoukankan      html  css  js  c++  java
  • 「 CODE[VS] P2853 」 方格游戏

    题目大意

    给定一张 $n imes n$ 的网格。每个格子上都有一个系数 $a$,先下 $A$ 和 $B$ 两人选择两条 $(1,1) ightarrow (n,n)$ 路径。要求着两条路径不能相同。并且要计算出两条路径每一个相对应的格子上的系数的差的绝对值之和。

    要求选择路径是满足下列条件:

    只能选择坐标增加的方向。

    解题思路

    棋盘 DP。

    既然是在一个棋盘中。并且已经规定了行走的方向。所以在移动的格子的数量相同时。两个路径停留的点到 $(1,1)$ 这个点的曼哈顿距离(横坐标$+$纵坐标)是相同的。而且知道了横坐标和曼哈顿距离就可以求出点的纵坐标。

    设 $DP[i][j][k]$ 表示两条路径停留点的横坐标分别是 $i$ 和 $j$,距离 $(1,1)$ 这个点的曼哈顿距离是 $k$。

    我们考虑枚举曼哈顿距离和两条路径所停留点的横坐标。这样通过横坐标和曼哈顿距离就可以求出纵坐标。如题所说,每一个点只能被他上面或者左边的点到达,所以能够得到下面的方程

    $$dp[i][j][k] = max{dp[i][j-1][k-1],dp[i-1][j][k-1],dp[i][j][k-1],dp[i-1][j-1][k-1]}+abs(a[i][k-i]-a[j][k-j])$$

    附上代码

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int INF = 2147483640;
    int n, a[103][103], dp[103][103][203];
    inline int ABS(int a) {
        return a>0 ? a : -a;
    }
    inline int MAX(int x, int y) {
        return x>y ? x : y;
    }
    int main() {
        scanf("%d", &n);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                scanf("%d", &a[i][j]);
        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-1][k-1]), MAX(dp[i][j][k-1], dp[i-1][j-1][k-1])) + ABS(a[i][k-i]-a[j][k-j]);
                }
            }
        }
        printf("%d", dp[n][n][2*n]);
    }
  • 相关阅读:
    运维必备:Oracle自备份精简教程(linux及win)
    Ansible11:变量详解【转】
    Ansible10:Playbook的角色与包含【转】
    Nginx下Redmine配置
    centos 6.5下安装mysql+nginx+redmine 3.1.0 笔记
    nginx 出现413 Request Entity Too Large问题的解决方法
    linux 安装redmine 遇到的问题
    linux编译ruby1.8.7 出现OPENSSL错误
    Linux下安装项目管理工具Redmine
    (转载)Go语言开发环境配置
  • 原文地址:https://www.cnblogs.com/bljfy/p/9579346.html
Copyright © 2011-2022 走看看