**洛谷P1605 迷宫 **
题目背景
给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
题目描述
无
输入格式
第一行N、M和T,N为行,M为列,T为障碍总数。第二行起点坐标SX,SY,终点坐标FX,FY。接下来T行,每行为障碍点的坐标。
输出格式
给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。
输入输出样例
输入 #1 复制
2 2 1
1 1 2 2
1 2
输出 #1 复制
1
说明/提示
【数据规模】
1≤N,M≤5
首先是我写的代码
#include<limits.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<iomanip>
using namespace std;
int m,n,t,cnt=0;
bool board[6][6]={},vis[6][6]={};
struct V{
int x,y;
}sta,rig,ob;
void sol(int x,int y){
if(x<1||y<1||x>n||y>m||board[x][y]==1||vis[x][y]==1)
return;
if(x==rig.x&&y==rig.y){
cnt++;
return;
}
vis[x][y]=1;
sol(x-1,y);
sol(x+1,y);
sol(x,y+1);
sol(x,y-1);
vis[x][y]=0;//回溯这一步很关键,跟装船那道题一样,为啥,函数末尾了有啥可回溯的
}
int main(){
cin>>n>>m>>t;
cin>>sta.x>>sta.y>>rig.x>>rig.y;
for(int i=0;i<t;i++){
cin>>ob.x>>ob.y;
board[ob.x][ob.y]=1;
}
sol(sta.x,sta.y);
cout<<cnt<<endl;
return 0;
}
问题就是如上所述,不能理解为什么末尾要回溯,回溯完了给谁用呢?
下面是洛谷上看到的解法
#include<iostream>
using namespace std;
int go[4][2]={-1,0,0,1,1,0,0,-1};
int n,m,t,x1,y1,x2,y2,f[6][6],q[6][6],ans;
void dfs(int x,int y)
{
int i,a,b,j;
if(x==x2&&y==y2)//到达终点,输出
ans++;
else
{
for(i=0;i<4;i++)//向四个方向枚举
{
a=x+go[i][0];
b=y+go[i][1];
if(a>0&&a<=n&&b>0&&b<=m&&f[a][b]==0&&q[a][b]==0)//判断可否走
{
q[a][b]=1;
dfs(a,b);
q[a][b]=0;
}
}
}
}
int main()
{
int i,z,u;
cin>>n>>m>>t>>x1>>y1>>x2>>y2;
for(i=0;i<t;i++)
{
cin>>z>>u;
f[z][u]=1;
}
q[x1][y1]=1;
ans=0;
dfs(x1,y1);
cout<<ans;
return 0;
}
好像别人给的这个解像是拔牙那种递归了,这里的回溯看起来合情合理,但这两种解法应该是一致的,所以说,问题在于?
对于函数调用的认知错误
#include<iostream>
using namespace std;
void y(){
cout<<4<<endl;
}
void t(){
cout<<3<<endl;
y();
}
void o(){
cout<<1<<endl;
t();
}
int main(int argc, const char * argv[]){
o();
cout<<2<<endl;
return 0;
}
假装自己在递归,通过打断点我们发现:不写return的函数在执行到末尾时仍然返回到上一级调用处,破案了朋友们!末尾的回溯使得上级函数在调用下个同级函数时还原了数据。