• 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]);
    }
  • 相关阅读:
    [noip2018]day1
    [CF1110d]JONGMAH
    BZOJ 2733 [HNOI2012]永无乡
    BZOJ 3123 [SDOI2013] 森林
    Nowcoder 练习赛26E 树上路径
    Luogu 2575 高手过招-SG函数
    BZOJ 1123[POI2008]BLO-Tarjan
    Nowcoder OI赛制测试2 F 假的数学题
    Luogu 2467[SDOI2010]地精部落
    Luogu 2216[HAOI2007]理想的正方形
  • 原文地址:https://www.cnblogs.com/rmy020718/p/9572843.html
Copyright © 2020-2023  润新知