zoukankan      html  css  js  c++  java
  • 51nod 更难的矩阵取数问题(动态规划)

    更难的矩阵取数问题

    给定一个m行n列的矩阵,矩阵每个元素是一个正整数,你现在 在左上角(第一行第一列),你需要走到右下角(第m行,第n列),每次只能朝右或者下走到相邻的位置,不能走出矩阵。然后再从右下角返回到左上角,这时只 能朝上或者左走,两次如果经过同一个格子,则该数字只计算一次,所有走过的数的总和作为你的得分,求最大的得分。

     
    输入

    第1行:2个数M N,中间用空格分隔,为矩阵的大小。(2 <= M, N <= 200)
    第2 - N + 1行:每行M个数,中间用空格隔开,对应格子中奖励的价值。(1 <= A[i,j] <= 10000)
    输出
    输出能够获得的最大价值。
    输入示例
    3 3
    1 3 3
    2 1 3
    2 2 1
    输出示例
    17
    请选取你熟悉的语言,并在下面的代码框中完成你的程序,注意数据范围,最终结果会造成Int32溢出,这样会输出错误的答案。
    不同语言如何处理输入输出,请查看下面的语言说明。
     
    【分析】
     
    没招了么?其实我们可以“两个人一起”dp(让两个人同时走)。

    用dp[x1][y1][x2][y2]表示第一个人在(x1,y1) 并且第二个人在(x2,y2)时的最大值。

    我们有初值dp[1][1][1][1] = a[1][1], 求的是dp[m][n][m][n]。

    问题来了: 每个人走一步,状态转移是什么?

    dp[x1][y1][x2][y2] = max{dp[x1’][y1’][x2’][y2’]} + a[x1][y1] + a[x2][y2]
    其中(x1’,y1’)是(x1,y1)的邻居,(x2’,y2’)是(x2,y2)的邻居。

    事实上,因为我们有这个等式提示我们其实只要用3维就可以表示这个矩阵,因为 y2 = x1 + y1 – x2所以那一维可以用走多少步表示出来。
     
    dp[step + 1][x1][x2] = max{dp[step][x1’][x2’]} + a[x1][y1] + a[x2][y2]
     
    图中为step做了编号。
    然而这个dp并没有体现出走到相同格子,数字仅计算一次的要求。那么我们加上这个条件:如果x1 = x2,dp[step + 1][x1][x2] = max{dp[step][x1’][x2’]} + a[x1][y1]。
     
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <list>
    #define inf 0x3f3f3f3f
    typedef long long ll;
    using namespace std ;
    #define inf 0x3f3f3f3f
    #define maxn 201
    int M[maxn][maxn];
    int dp[maxn<<1][maxn][maxn];
    int main()
    {
        int n,m,i,j,x1,x2;
        scanf("%d%d",&m,&n);
        for(i=1;i<=n;++i)
            for(j=1;j<=m;++j)
                scanf("%d",&M[i][j]);
        memset(dp,0,sizeof(dp));
    
        for(i=1;i<n+m;++i)
            for(x1=1;x1<=n&&i-x1>=0;++x1)
                for(x2=1;x2<=n&&i-x2>=0;++x2)
                {
    
                        dp[i][x1][x2]=max(dp[i][x1][x2],dp[i-1][x1-1][x2-1]+M[x1][i-x1+1]+(x1==x2?0:M[x2][i-x2+1]));
    
                        dp[i][x1][x2]=max(dp[i][x1][x2],dp[i-1][x1-1][x2]+M[x1][i-x1+1]+(x1==x2?0:M[x2][i-x2+1]));
    
                        dp[i][x1][x2]=max(dp[i][x1][x2],dp[i-1][x1][x2-1]+M[x1][i-x1+1]+(x1==x2?0:M[x2][i-x2+1]));
    
                        dp[i][x1][x2]=max(dp[i][x1][x2],dp[i-1][x1][x2]+M[x1][i-x1+1]+(x1==x2?0:M[x2][i-x2+1]));
                        //printf("dp[%d][%d][%d]=%d
    ",i,x1,x2,dp[i][x1][x2]);
                }
        printf("%d
    ",dp[n+m-1][n][n]);
        return 0;
    }
    View Code
  • 相关阅读:
    hdu7047 /2021“MINIEYE杯”中国大学生算法设计超级联赛(7) 1004 Link with Balls
    hdu7115 Vertex Deletion
    CF1552B B. Running for Gold
    hdu7055 /2021“MINIEYE杯”中国大学生算法设计超级联赛(7) 1012 Yiwen with Sqc
    hdu7050 /2021“MINIEYE杯”中国大学生算法设计超级联赛(7) 1007 Link with Limit
    CF 1560E E. Polycarp and String Transformation(思维)
    CF 1542C C. Strange Function
    STL 算法 std::distance
    STL 算法 std::accumulate
    std::get<C++11多线程库~线程管理>(08):转移线程所有权(2)
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/5709132.html
Copyright © 2011-2022 走看看