一.题目
资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
输入格式
第一行输入一个正整数n。
以下n行描述该方格。金币数保证是不超过1000的正整数。
输出格式
最多能拿金币数量。
样例输入
3
1 3 3
2 2 2
3 1 2
样例输出
11
数据规模和约定
n<=1000
二.AC代码(C语言)
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
scanf("%d",&n);
int gold[n+1][n+1];
int i,j,q,p;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&gold[i][j]);
}
}
int get[n+1][n+1];
for(q=1;q<=n;q++)
{
for(p=1;p<=n;p++)
{
if(q==1&&p==1)
{
get[1][1] = gold[1][1];
}
else
{
if(q==1)
{
get[q][p]=get[q][p-1]+gold[q][p];
}
else if(p==1)
{
get[q][p]=get[q-1][p]+gold[q][p];
}
else
{
int temp = get[q-1][p]>=get[q][p-1]?(get[q-1][p]):(get[q][p-1]);
get[q][p]=gold[q][p]+temp;
}
}
}
}
printf("%d",get[n][n]);
return 0;
}
三.讲解
首先,这是一个DP问题,后者的状态取决于前者。
之后,我们创建两个二维数组,一个gold数组用于存储输入的金币数,一个get数组用于存储此位置可以获得的最大的金币数。
然后我们分三种情况分析。
第一行每个位置获得的最大金币数只与它左边获得的最大金币数有关,即
get[q][p]=get[q][p-1]+gold[q][p]
第一列每个位置获得的最大金币数只与它上边获得的最大金币数有关,即
get[q][p]=get[q-1][p]+gold[q][p]
其他常规位置获得的最大金币数取决于它左边和它上边的最大金币数中大的那个,即
get[q][p]=gold[q][p]+temp
最后还要记得将get[1][1]单独拿出来。
不知道有没有不需要单独处理[1][1]位置的方法呢,希望各位大佬评论一下。