【南桥杯】算法训练 拿金币 C++解法

问题描述
  有一个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问题,那么应该要分三种情况:

  1. 如果当前DP[i][j]是不在左边界和上边界的格子,那么该格子中DP[i][j]=max(DP[i-1][j],DP[i][j-1])+num[i][j];
  2. 如果当前格子是在左边界,那么应该是DP[i][j]=DP[i-1][j]+num[i][j] (此时j=0);
  3. 如果是有右边界,应该是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;
}

南桥杯测试结果为满分,这种写法可以用~

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值