zoukankan      html  css  js  c++  java
  • 计蒜客 动态规划基础 蒜头君的城堡之旅

    规划基础 蒜头君的城堡之旅

    题目:

    蒜国地域是一个 n 行 m 列的矩阵,下标均从 1 开始。蒜国有个美丽的城堡,在坐标 (n,m) 上,蒜头君在坐标 (1,1) 的位置上。蒜头君打算出发去城堡游玩,游玩结束后返回到起点。在出发去城堡的路上,蒜头君只会选择往下或者往右走,而在返回的路上,蒜头君只会选择往上或者往左走,每次只能走一格。已知每个格子上都有一定数量的蒜味可乐,每个格子至多经过一次。
    现在蒜头君请你来帮他计算一下,如何计划来回行程,可以收集到最多的蒜味可乐。

    输入格式

    第一行输入两个整数 n,m(1≤n,m≤50),表示蒜国是一个 n 行 m 列的矩阵。
    接下来输入 n 行,每行输入 m 个整数,代表一个 n×m 的矩阵,每个整数代表对应位置上的蒜味可乐数量,每行的每两个整数之间用一个空格隔开。其中蒜头君的位置和城堡的位置上没有蒜味可乐,用 0 表示,其余位置上的整数范围在 [1,100] 内。

    输出格式

    输出一行,输出一个整数,表示蒜头君在来回路上能收集到的蒜味可乐的最大值。

    样例输入

    3 3
    0 2 9
    4 8 6
    2 7 0

    样例输出

    36

    分析:

    (可以理解为从起点出发的不相交的两条路径)
    首先,要注意一个问题:不能先算出去的最大值,再算返回的最大值。这样可能导致只保证了去的最大值,但没有保证来回之和的最大值。也就是说,来回的优先级是相同的,但是如果先算去路的最大值就会使得去的优先级高于回的优先级。
    容易注意到本题的范围不大,所以可以用一个四维数组: f[i][j][k][l] 来表示路径1走到 [i][j] 和路径2走到 [k][l] 的和的最优值。
    其中,因为走的步数相同,所以 i+j=k+l (可以利用这个等式来把空间和时间复杂度降一级),不难想到只要当前一步的两条路径没有走到用一个点,两条路径就不会相交(如果相交,重叠部分的可乐只能领取一次,就不是最优情况)。
    最后就不难写出动规方程:  f[i][j][k][l] = max(max(f[i-1][j][k-1][l], f[i][j-1][k-1][l]), max(f[i-1][j][k][l-1], f[i][j-1][k][l-1]))+map[i][j]+map[k][l]; 其中第一部分是求两个路径当前点的两个前趋情况的和的最大值(一共是 2×2 四种情况,所以用了一个 max 套两个 max)。
    最最后,因为两条路径在终点还是会交于一点,所以千万不能输出 f[n][m][n][m] ,应该输出 f[n-1][m][n][m-1] 。
     

    标程:

     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstring>
     4 using namespace std;
     5 int n,m,map[55][55],f[55][55][55][55];
     6 int main()
     7 {
     8     memset(f,0,sizeof(f));
     9     cin >> n >> m;
    10     for (int i=1; i<=n; i++)
    11     {
    12         for (int j=1; j<=m; j++)
    13         {
    14             cin >> map[i][j];
    15         }
    16     }
    17     for (int i=1; i<=n; i++)
    18     {
    19         for (int j=1; j<=m; j++)
    20         {
    21             for (int k=1; k<=n; k++)
    22             {
    23                 for (int l=1; l<=m; l++)
    24                 {
    25                     if (i+j!=k+l)
    26                         continue;
    27                     if (i==k && j==l)
    28                         continue;
    29                     f[i][j][k][l] = max(max(f[i-1][j][k-1][l], f[i][j-1][k-1][l]), max(f[i-1][j][k][l-1], f[i][j-1][k][l-1]))
    30                     +map[i][j]+map[k][l];
    31                 }
    32             }
    33         }
    34     }
    35     cout << f[n-1][m][n][m-1] << endl;
    36     return 0;
    37 }
  • 相关阅读:
    js截取字符串区分汉字字母代码
    List 去处自定义重复对象方法
    63. Unique Paths II
    62. Unique Paths
    388. Longest Absolute File Path
    41. First Missing Positive
    140. Word Break II
    139. Word Break
    239. Sliding Window Maximum
    5. Longest Palindromic Substring
  • 原文地址:https://www.cnblogs.com/OIerPrime/p/7674569.html
Copyright © 2011-2022 走看看