洛谷P1605 迷宫

**洛谷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的函数在执行到末尾时仍然返回到上一级调用处,破案了朋友们!末尾的回溯使得上级函数在调用下个同级函数时还原了数据。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值