zoukankan      html  css  js  c++  java
  • 洛谷

    题目链接 : https://www.luogu.com.cn/problem/P1006

    想到了用四维数组来枚举的,但是不太明白如何判重。后来才明白,只需要令 x2 > x1 即可

    先来分析状态转移方程 :

    dp[ x1 ][ y1 ][ x2 ][ y2 ]   = max(   max( dp[ x1 + 1 ][ y1 ][ x2+1 ][ y2 ] , dp[ x1 ][ y1+1 ][ x2 ][ y2+1 ]   )

                                                   max( dp[ x1+1 ][ y1 ][ x2 ][ y2+1 ] , dp[ x1 ][ y1+1 ][ x2+1 ][ y2 ]     )

                                                )   + board[ x1 ][ y1 ] + board[ x2 ][ y2 ]

    它表示,对于某一个时刻, A在位置 ( x1,y1 ) , B在位置( x2,y2 ),它可以由4种途径得到:分别为 A的两种方式到达 (x1,y1) 和 B的两种方式到达( x2,y2 )的四种组合。最后加上新得到的分数

    接下来还剩下三个问题:

    < 1 > dp初值条件:这个好说,就是 0。(补充一点:题目要求来回传纸条,等价于一个人传给另一个人两张纸条。这样可以方便的固定dp起点 )

    < 2 > dp的循环顺序:由于是从 右下角的(x,y) 走到左上角的(1,1) , 每一个靠左上方的点的状态,都需要由靠右方、下方的点的状态推得,故变量由 x -> 1,  y -> 1,表示从右下向左上推导。

    < 3 > dp终点?由于我们控制了 x2 > x1 , 故最终不可能得到 dp[1][1][1][1]的状态,而应该是即将变为dp[1][1][1][1]的状态,也就是 -->  dp[2][1][1][2]

    另外:

    四层嵌套for循环的合理性?

    首先在避免重复的这一点上肯定是合理的(限制了x2 > x1)

    现在只需要考虑: 为什么这样的循环顺序,即现枚举x1的一个状态,再枚举所有的x2状态这种做法合理?

    动手画画图可以知道,实际上遍历的顺序是 -> 外两层循环在按照从右到左、从下到上的顺序遍历每一个A的位置 (x1,y1),内两层循环针对每一种(x1,y1)遍历所有 x1 右边的矩形范围内的点(x2,y2)。因此一定可以得到每一种无交点的传递纸条途径。

    循环最终得到的x1的最终位置为(1,1),x2的最终位置为(2,1)。但是由于  (x1,y1)为(1,1)时,按照我们的状态方程,它会将 1,2纳入考虑范围内,但是实际上A不可能走到(1,2),否则会与B的路径相交,故最终答案存储在 dp[2][1][1][2] 中。

     1 #include <iostream>
     2 #define Maxsize 5
     3 using namespace std;
     4 int board[Maxsize][Maxsize];
     5 int f[Maxsize][Maxsize][Maxsize][Maxsize];
     6     //   x1      y1       x2       y2
     7 int main(){
     8     int x,y;
     9     cin >> x >> y;
    10     for(int i = 1; i <= x; i++){
    11         for(int j = 1; j <= y; j++){
    12             cin >> board[i][j];
    13         }
    14     }
    15     for(int x1 = x; x1 >= 1; x1--)
    16         for(int y1 = y; y1 >= 1; y1--)
    17             for(int x2 = x1 + 1; x2 >= 1; x2--)
    18                 for(int y2 = y; y2 > y1; y2--){
    19                     f[x1][y1][x2][y2] = max(
    20                         max( f[x1+1][y1][x2+1][y2] , f[x1][y1+1][x2][y2+1] ),
    21                         max( f[x1+1][y1][x2][y2+1] , f[x1][y1+1][x2+1][y2] )
    22                                         )
    23                     + board[x1][y1] + board[x2][y2];
    24                 }
    25     cout<<f[1][1][1][2];
    26     cout<<f[2][1][1][2];
    27     return 0;
    28 }
    ---- suffer now and live the rest of your life as a champion ----
  • 相关阅读:
    【并发编程】安全发布对象
    【并发编程】并发的学习步骤
    特殊字符
    【并发编程】【JDK源码】CAS与synchronized
    【并发编程】【JDK源码】JDK的(J.U.C)java.util.concurrent包结构
    【JDK源码】将JDK源码导入IDEA中
    【Linux命令】用户及分用户组
    【Linux命令】linux一次性解压多个.gz或者.tar.gz文件
    悟透JavaScript
    设计模式------工厂模式和抽象工厂模式
  • 原文地址:https://www.cnblogs.com/popodynasty/p/12144934.html
Copyright © 2011-2022 走看看