1038.收集宝藏
Time Limit: 1500 MS Memory Limit: 32768 KB
Total Submission(s): 280 Accepted Submission(s): 142
Description
有一个n*n的矩阵,矩阵每个格子中都有一些宝藏,从左上角(1, 1)出发,每次只能向下或者向右移动一格,已知每个格子中宝藏的价值,求走到右下角(n, n)时能收集到的宝藏的总最大价值。
Input
第一行为一个整数n(1 <= n <= 1000),表示矩阵的行、列数。
接下来n行,每行n个整数,每个整数表示当前格子的宝藏价值(不超过10000)。
Output
一个整数,表示能收集到的宝藏的最大总价值。
Sample Input
4 1 2 3 10 3 4 1 1 5 2 1 1 1 3 1 1
Sample Output
19
Source
Unknown
这个题简单分析下:正方形矩阵由左上角走到右下角求获得宝藏的最大值。
两种方法1.记忆化搜索不断记录,不断比较找到最大的方式.
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int u[1010][1010];
int sum[1000][1000];
int n;
int rec(int a,int b)
{
if(sum[a][b]!=-1)
return sum[a][b];/*当遍历到矩阵外或者已经有了sum值则直接返回。*/
/*在这里我们不必担心返回的会不会不是最大值,因为下面的遍历每一次都是获得的其最大值。因而在这个sum数组中的也一定是最大值*/
// if(sum[a][b]>=0)
// return sum[a][b];
int nx = rec(a+1,b);
int ny = rec(a,b+1);
sum[a][b] = max(nx,ny)+u[a][b];
return sum[a][b];
}
int main()
{
scanf("%d",&n);
memset(sum,0,sizeof(sum));
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
scanf("%d",&u[i][j]);
sum[i][j]=-1;//记录矩阵。有矩阵的地方记录为-1.
}
}
int res = rec(0,0);
printf("%d\n",res);
}
2.动态规划
递推方程
sum[i][j] = max(sum[i-1][j],sum[i][j-1]) +u[i][j];
可以想象下矩阵除两条边边界外而且只能左移和下移。所以满足上述递推式。所以我们只需特殊处理两条边边界即可。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int u[1010][1010];
int sum[1000][1000];
int n;
int main()
{
scanf("%d",&n);
memset(sum,0,sizeof(sum));
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
scanf("%d",&u[i][j]);
}
}
sum[0][0] = u[0][0];
for(int i = 1;i<n;i++)
{
sum[0][i] = sum[0][i-1]+u[0][i];/*处理边界问题因为只有边界不满足递推式*/
sum[i][0] = sum[i-1][0]+u[i][0];
}
for(int i = 1;i<n;i++)
{
for(int j =1;j<n;j++)
{
sum[i][j] = max(sum[i-1][j],sum[i][j-1]) +u[i][j];
}
}
printf("%d\n",sum[n-1][n-1]);
}