• 51Nod 1084:矩阵取数问题 V2(多维DP)


    1084 矩阵取数问题 V2 

    基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题

     收藏

     关注

    一个M*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,先从左上走到右下,再从右下走到左上。第1遍时只能向下和向右走,第2遍时只能向上和向左走。两次如果经过同一个格子,则该格子的奖励只计算一次,求能够获得的最大价值。

    例如:3 * 3的方格。

    1 3 3

    2 1 3

    2 2 1

    能够获得的最大价值为:17。1 -> 3 -> 3 -> 3 -> 1 -> 2 -> 2 -> 2 -> 1。其中起点和终点的奖励只计算1次。

    Input

    第1行:2个数M N,中间用空格分隔,为矩阵的大小。(2 <= M, N <= 200)
    第2 - N + 1行:每行M个数,中间用空格隔开,对应格子中奖励的价值。(1 <= A[i,j] <= 10000)

    Output

    输出能够获得的最大价值。

    Input示例

    3 3
    1 3 3
    2 1 3
    2 2 1

    Output示例

    17

    思路

    看做是两个人(假设是A,B)同时从左上角往右下角走,两个人相遇的时候只加一个格子里的数字。因为每次只能往右或往下走,所以从起点到终点走的距离是一定的,即m+n。

    用dp[x1][y1][x2][y2]来记录A到达(x1,y1)和B到达(x2,y2)的最大数字和。然而这种写法太占空间了,四维数组,应该会爆内存的,所以需要对其进行优化

    设当前走的步数为s,则y1=s-x1;y2=s-x2(因为每次只能走一步,只能向右或向下,所以总步数=横坐标+纵坐标)。dp数组就可以写成dp[s][x1][x2](表示走了s步,A在x1位置和B在x2位置取到数字的最大和)。

    所以状态转移方程就可以写成:

    当A,B不在同一点时:dp[s][x1][x2]=max(dp[s-1][x1'][x2'])+a[x1][y1]+b[x2][y2]

    A,B在同一点时:dp[s][x1][x2]=max(dp[s-1][x1'][x2'])+a[x1][y1]

    最后要注意输入问题,输入的第一个数是列,第二个是行(因为这个输入疯狂WA

    AC代码

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #include <limits.h>
    #include <map>
    #include <stack>
    #include <queue>
    #include <vector>
    #include <set>
    #include <string>
    #define ll long long
    #define ms(a) memset(a,0,sizeof(a))
    #define pi acos(-1.0)
    #define INF 0x3f3f3f3f
    const double E=exp(1);
    const int maxn=250;
    using namespace std;
    int dp[maxn*2][maxn][maxn];
    int a[maxn][maxn];
    int main(int argc, char const *argv[])
    {
    	ios::sync_with_stdio(false);
    	int n,m;
    	ms(dp);
    	cin>>m>>n;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			cin>>a[i][j];
    	for(int s=2;s<=n+m;s++)
    	{
    		for(int x1=1;x1<=n;x1++)
    		{
    			for(int x2=1;x2<=n;x2++)
    			{
    				int y1=s-x1;
    				int y2=s-x2;
    				if(y1>=1&&y2>=1&&y1<=m&&y2<=m)
    				{
    					dp[s][x1][x2]=max(dp[s-1][x1-1][x2],max(dp[s-1][x1][x2-1],max(dp[s-1][x1][x2] ,dp[s-1][x1-1][x2-1])));
    					if(x1==x2)
    						dp[s][x1][x2]+=a[x1][y1];
    					else
    						dp[s][x1][x2]+=a[x1][y1]+a[x2][y2];
    				}
    			}
    		}
    	}
    	cout<<dp[n+m][n][n]<<endl;
    	return 0;
    }
    
  • 相关阅读:
    18.中介者模式
    17.迭代器模式
    16.解释器模式
    15.命令模式
    Git超详细用法,通俗易懂
    CSS Sprites精灵图(雪碧图)
    小程序被冻结,忘记原始ID,如何找回?
    vue组件-视频播放之video.js
    基础设计模式-04 复杂对象创建的建造器模式
    基础设计模式-03 从过滤器(Filter)校验链学习职责链模式
  • 原文地址:https://www.cnblogs.com/Friends-A/p/10324401.html
Copyright © 2020-2023  润新知