问题描述
有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
输入格式
第一行输入一个正整数n。
以下n行描述该方格。金币数保证是不超过1000的正整数。
输出格式
最多能拿金币数量。
样例输入
3
1 3 3
2 2 2
3 1 2
样例输出
11
数据规模和约定
n<=1000
首先看到这个我问题的时候我想好像也可以用暴力搜索达到求解(在忽略复杂度情况下),然后我快速地用DFS完成代码,其实在编写的过程中就感觉有点问题,没有考虑如果某一个格子的右边格子和下面格子相等的情况该怎么搜索的问题,所以果断放弃这种做法,老老实实采用DP算法实现,以下是用搜索写的部分代码(没有完成相等的情况,如果有大佬看见能否提一下自己好的想法,我会好好学的!)
#include<iostream>
#define Max 1002
using namespace std;
int Money[Max][Max];
int Sum_Money=0;
int Serch(int x,int y){
if(Sum_Money==0) Sum_Money=Money[x][y];
if(Money[x][y+1]==0&&Money[x+1][y]==0){
return Sum_Money;
}
else{
if(Money[x][y+1]>Money[x+1][y]){
Sum_Money+=Money[x][y+1];
Serch(x,y+1);
}
else if(Money[x][y+1]<=Money[x+1][y]){
Sum_Money+=Money[x+1][y];
Serch(x+1,y);
}
else{ //相等的情况
}
}
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>Money[i][j];
}
}
Serch(1,1);
cout<<Sum_Money<<endl;
}
如果采用DF问题,那么应该要分三种情况:
- 如果当前DP[i][j]是不在左边界和上边界的格子,那么该格子中DP[i][j]=max(DP[i-1][j],DP[i][j-1])+num[i][j];
- 如果当前格子是在左边界,那么应该是DP[i][j]=DP[i-1][j]+num[i][j] (此时j=0);
- 如果是有右边界,应该是DP[i][j]=DP[i][j-1]+num[i][j](此时i=0)
注:这里的DP[i][j]不是构建的金币迷宫,num[i][j]才是,DP[i][j]是迷宫在此路径上所能得到的最大金币数
C++代码实现如下:
#include<iostream>
#define Max 1002
using namespace std;
int num[Max][Max];
int DP[Max][Max];
int MAX(int x,int y){
return x>y?x:y;
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>num[i][j];
DP[i][j]=0;
}
}
//初始化dp[1][1],即左上角
DP[1][1]=num[1][1];
for(int i=1;i<=n;i++){
DP[i][1]=DP[i-1][1]+num[i][1]; //左边界
DP[1][i]=DP[1][i-1]+num[1][i]; //上边界
}
for(int i=2;i<=n;i++){
for(int j=2;j<=n;j++){
DP[i][j]=MAX(DP[i-1][j],DP[i][j-1])+num[i][j];
}
}
cout<<DP[n][n]<<endl;
return 0;
}
南桥杯测试结果为满分,这种写法可以用~