题目描述
一天小包同学利用AI元宇宙设备在湿地公园里探险玩挖金币游戏,湿地公园被划分为 n×m 个网格,每个格点内都有一座宫殿, 每个宫殿都有一个数字,代表该宫殿内的金币,当小包同学第一次到达某个宫殿时就会拿走宫殿内的金币,并且该宫殿会沦陷消失不能再通过该点;当然有一些怪物会伪装成金币,踩到其退出游戏。通过搜集情报小包同学知道了怪物的伪装规则:怪物的数字会等于其相邻的上下左右四个宫殿数字的和。 已知当小包同学处在某个格点时,他只能移动到东南西北(或者说上下左右)四个方向之一的相邻格点上,小包同学想要活着从点 A(1,1)走到点 B(n,m)(均不为怪物),问在不走出湿地公园的情况下他最多能获得多少的金币?
输入格式
第一行为正整数 n(1<=n<10)和 m(0<=m<10),代表湿地公园的大小;
接下来 N 行,每行 M 个数字代表每个宫殿内的数字,注意:输入样例中标红的数字表示怪兽。
输出格式
输出一行一个整数,代表小包同学获得的最大金币数。若小包同学不能活着走到 B 点请输出 -1。
输入输出样例
输入样例1:
5 5
1 4 8 6 10
3 1 4 5 8
1 6 4 11 1
2 0 2 1 2
1 3 2 7 2
输出样例1:
66
说明
数据范围:对于 100%的数据,1<=n,m<10;
样例一解释:
样例一中标红的数字为怪兽,经计算,所以能经过最大的路径为1 4 8 6 10 8 5 4 4 2 2 7 1 2 2 总和为66。
【解析】
1:本题属于一个正规的搜索回溯题目,dfs过程中考虑一些特殊情况进行剪枝。
#include <iostream>
using namespace std;
const long long INF=0x3f3f3f3f; // 一开始我设置 -1 ,想着这里面应该都是正数吧。但没有通过。改成无穷大就过了。
long long n,m,a[12][12],ans=-1;
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
void judge(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int s=0;
if(i-1>=1) s+=a[i-1][j];
if(i+1<=n) s+=a[i+1][j];
if(j-1>=1) s+=a[i][j-1];
if(j+1<=m) s+=a[i][j+1];
if(s==a[i][j]){
a[i][j]=INF;
}
}
}
}
void dfs(long long x,long long y,long long s){
if(x==n&&y==m){
ans=max(ans,s);
return;
}
if(a[x][y]==INF){
return;
}
for(int i=0;i<4;i++){ // 上下左右
int xx=x+dx[i];
int yy=y+dy[i];
if(xx<1||xx>n||yy<1||yy>m||a[xx][yy]==INF){ // -1 说明不能走或者已经走过
continue;
}
int t=a[x][y];
a[x][y]=INF;
dfs(xx,yy,s+a[xx][yy]);
a[x][y]=t;
}
}
int main()
{
cin>>n>>m;
if(m==0){
cout<<-1;
return 0;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
judge();
dfs(1,1,a[1][1]);
cout<<ans;
return 0;
}