矩阵取数问题总结(ⅠⅡ)

#先看第一题

一个N*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,从左上走到右下,只能向下向右走,求能够获得的最大价值。
例如:3 * 3的方格。
1 3 3
2 1 3
2 2 1
能够获得的最大价值为:11。
Input
第1行:N,N为矩阵的大小。(2 <= N <= 500)
第2 - N + 1行:每行N个数,中间用空格隔开,对应格子中奖励的价值。(1 <= Nii <= 10000)
Output
输出能够获得的最大价值。
Sample Input
3
1 3 3
2 1 3
2 2 1
Sample Output
11

简单dp直接ac.

#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
int r[1001][1001],dp[1001][1001];//r用来存数据,dp用来存最大值
int main(){
    int num;
    memset(r,0,sizeof(r));
    memset(dp,0,sizeof(dp));
    scanf("%d",&num);
    for(int i=1;i<=num;i++){
        for(int j=1;j<=num;j++){
            scanf("%d",&r[i][j]);
        }
    }
    for(int i=1;i<=num;i++){
        for(int j=1;j<=num;j++){
            dp[i][j]=max(dp[i-1][j],dp[i][j-1])+r[i][j];
        }
    }
    printf("%d\n",dp[num][num]);
    return 0;
}

#再看第二题

一个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 <= Ai,ji,j <= 10000)
Output
输出能够获得的最大价值。
Sample Input
3 3
1 3 3
2 1 3
2 2 1
Sample Output
17

这一道题我解了四个小时之久,实在是难受到不要不要的,复习时要好好看看才行呀。
先把代码贴上吧

#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=210;
#define MAX(a,b,c,d) max(max(a,b),max(c,d))//函数声明
int r[maxn][maxn],dp[510][maxn][maxn];
int main(){
    int row,col;
    memset(r,0,sizeof(r));
    memset(dp,0,sizeof(dp));
    scanf("%d%d",&col,&row);
    for(int i=1;i<=row;i++){
        for(int j=1;j<=col;j++){
            scanf("%d",&r[i][j]);
        }
    }
    for (int k = 2; k <= col+row ; k++){//k代表已经走得步数
        for (int i = 1; i <= row && k - i > 0; i++){//i代表第一个人所在的一列
            for (int j = 1; j <= row && k - j > 0; j++){//j代表第二个人所在的一列
                dp[k][i][j] =MAX(dp[k - 1][i][j],
						dp[k - 1][i - 1][j - 1],
						dp[k - 1][i - 1][j],
						dp[k - 1][i][j - 1])
				+ r[i][k - i] + (i == j ? 0 : r[j][k - j]);//公式的意思代表如果i==j时返回0,否则返回r[j][k - j]
            }
        }
    }
    printf("%d\n",dp[col+row][row][row]);
    return 0;
}

##误区

1.刚开始时就是不理解步数代表的是什么,前一个小时以为k代表的是两种路径的总步数,就是解释不清。k代表的是两种路径的步数,两种方法是同时开始的,k值是共同的。
2.关于i,j在代码中,i,j代表的是列,事实上也可以用行。由于总步数相同,那么他们的位置就可以用r[i][k-i],或者r[i][k-j]来表示。
3.搞不懂第二,三层循环的意思,循环是干什么的。那是一个纠结呀,脑子都要炸了。由于两条路线在一个矩阵中那么有可能移动方向就是在同一列只是不同行,也有可能是在同一行不在同一列,但是一切的前提条件就是每一个值都不能大于k。因为就算是都在同一行(列)移动,也不可能大于k的。
4.搞不懂为什么步数等于行+列,现在明白了,只有一个数字时,他也是一个11矩阵,等于2,所以如题中所述33的矩阵就是6,起始是从2开始的当然步数就是6了。

加油!早日脱白。。。

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旺旺的碎冰冰~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值