zoukankan      html  css  js  c++  java
  • [Swust OJ 1084]--Mzx0821月赛系列之情书(双线程dp)

    题目链接:http://acm.swust.edu.cn/problem/1084/

    Time limit(ms): 1000        Memory limit(kb): 65535
     
    Description

    小时候,Mzx0821暗恋班上的一个妹子Zzx。

        一次班上做活动,班上同学被安排坐成m行n列的矩阵,Mzx0821坐在坐标(x1,y1)的位置,Zzx坐在坐标(x2,y2)的位置。活动过程中,Mzx0821写了一张纸条想给Zzx,但是Mzx0821又不想班上其他人看到他写的内容,于是Mzx0821给班上每个人定义了一个保密程度值(就是这个人不偷看纸条内容的可能),每个人传递纸条只能给前后左右的人。

        Mzx0821还考虑到万一Zzx给Mzx0821回纸条怎么办呢,为了保密,Mzx0821希望每个人最多传递一次纸条,就是说一个人在Mzx0821传给Zzx的时候帮了忙,就不能再帮Zzx传给Mzx0821,反之亦然。

        Mzx0821希望找到这样两条路,使得来回两条路上的保密程度值的和最大,为了尽快传到,这两条路必须是Mzx0821到Zzx的之间的最短路。

        Mzx0821智商实在捉急,于是向机智的学弟学妹们求助,你能帮助他找到正确的路线吗?

    Input

    输入第一行有2个用空格隔开的整数m和n,表示班里有m行n列(1<=m,n<=50)。

    为了简化问题我们假设Mzx0821坐在左上角,Zzx坐在右下角。

    接下来的m行是一个m*n的矩阵,矩阵中第i行j列的整数表示坐在第i行j列的学生的保密程度。每行的n个整数之间用空格隔开。

    友情提示:Mzx0821坐标点的值和Zzx坐标点的值为0,坐标点的值<10000。

     
    Output

    输出共一行,包含一个整数,表示来回两条路上参与传递纸条的学生的保密程度之和的最大值。

     
    Sample Input
    3 3
    0 3 9
    2 8 5
    5 7 0

    Sample Output
    34

     
    输出换行请使用
     
     
    解题思路:一个简单的双线程dp,直接写就是了,两个人同一个方向同时走,dp[i][j][x][y],代表第一个人走到(i,j),第二个人走到(x,y)的最大值
     

    我们转化一下思想,题目中说由左上方到右下方来回,我们可以看作是从左上方找两条不相交的路径到右下方。这里我们可以好比是两个纸条同时从左上方向右下方传,只要保证在同一时刻两个纸条不在同一个人手里,那么我们就能保证两个字条的路径不相交.

      确定算法: DP(动态规划)
      状态:当前时刻的两个字条的坐标。

      状态转移方程式 :

      dp[i][j][x][y]= max{ dp[i-1][j][x-1][y],dp[i-1][j][x][y-1],dp[i][j-1][x-1][y],dp[i][j-1][x][y-1] }+mpt[i][j]+mpt[x][y]
      为了保证两个字条是同步传递的,所以方程式要加一个限定条件 ( i + j = x + y )☆
     
    代码如下:
     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 #define maxn 51
     7 int m, n, mpt[maxn][maxn];
     8 int dp[maxn][maxn][maxn][maxn];
     9 //同一个方向同时走
    10 //dp[i][j][x][y]代表当第一个人走到i,j且第二个人走到x,y时的最大值
    11 
    12 int max(int x, int y, int z, int w){
    13     return max(max(max(x, y), z), w);
    14 }
    15 int main()
    16 {
    17     while (cin >> m >> n){
    18         memset(dp, 0, sizeof(dp));
    19         for (int i = 1; i <= m; i++)
    20         for (int j = 1; j <= n; j++)
    21             cin >> mpt[i][j];
    22         for (int i = 1; i <= m; i++){
    23             for (int j = 1; j <= n; j++){
    24                 //第二个人走的路径在第一个人的下面,
    25                 for (int x = i + 1; x <= m; x++){
    26                     int y = i + j - x;
    27                     if (y <= 0)continue;
    28                     dp[i][j][x][y] = max(dp[i - 1][j][x - 1][y], dp[i - 1][j][x][y - 1], dp[i][j - 1][x][y - 1], dp[i][j - 1][x - 1][y]) + mpt[i][j] + mpt[x][y];
    29                 }
    30             }
    31         }
    32         //最后第一个人到终点的左边,第二个人到终点的右边
    33         cout << dp[m - 1][n][m][n - 1] << "
    ";
    34     }
    35     return 0;
    36 }
    View Code

     代码还可以优化成三维数组:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 #define maxn 51
     7 int m, n, mpt[maxn][maxn];
     8 int dp[maxn][maxn][maxn];
     9 //同一个方向同时走
    10 
    11 int max(int x, int y, int z, int w){
    12     return max(max(max(x, y), z), w);
    13 }
    14 int main()
    15 {
    16     while (cin >> m >> n){
    17         memset(dp, 0, sizeof(dp));
    18         for (int i = 1; i <= m; i++)
    19         for (int j = 1; j <= n; j++)
    20             cin >> mpt[i][j];
    21         for (int i = 1; i <= m; i++){
    22             for (int j = 1; j <= n; j++){
    23                 for (int x = 1; x < i; x++){
    24                     dp[i][j][x] = max(dp[i - 1][j][x - 1], dp[i - 1][j][x], dp[i][j - 1][x - 1], dp[i][j - 1][x]) + mpt[i][j] + mpt[x][i + j - x];
    25                 }
    26             }
    27         }
    28         //最后第一个人到终点的左边,第二个人到终点的右边
    29         cout << dp[m][n - 1][m - 1] << "
    ";
    30     }
    31     return 0;
    32 }
    View Code
  • 相关阅读:
    2星|《丰田一页纸极简思考法》:僵化、不易扩展、修改,价值不大
    4星|《亿万》:FBI大战华尔街对冲基金大鳄
    3星|《CMO到底能干多久?》:CEO必须决定供公司需要哪类CMO
    中老年创业成功率更高,美国投资人的创业指南:4星|《烧掉你的商业计划书》
    3星|《科技投资新时代》:TMT行业资讯汇编
    2星|史蒂芬·平克《风格感觉》:英语写作指导,不适合外行阅读
    3星|《故事课1》:7个步骤+36种情节+悬念,作者没有拿得出手的故事作品
    2.5星|《数字货币:世界为我疯狂》:5年来《商业周刊》的区块链与比特币相关的文章16篇
    2.5星|《哈佛商学院管理与MBA案例全书》:书名太唬人了,依据中文经管书汇编整理而成
    3.5星|《第一本经济学》:通俗、可信的经济学入门
  • 原文地址:https://www.cnblogs.com/zyxStar/p/4586193.html
Copyright © 2011-2022 走看看