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]);
    }
  • 相关阅读:
    关于动态规划的问题494_LEETCODE_TARGET_SUM
    Python 关于二叉树生成、先序遍历、中序遍历、后序遍历、反转
    关于python引入文件路径的解决办法
    git一些笔记
    迪克斯特拉 算法(算最短距离)
    Python多线程编程中daemon属性的作用
    types.MethodType实例绑定方法
    Python之__getitem__、__getattr__、__setitem__ 、__setitem__ 的区别
    jenkins自动打包ios、安卓
    python socket编程tcp/udp俩连接
  • 原文地址:https://www.cnblogs.com/bljfy/p/9579346.html
Copyright © 2011-2022 走看看