NYOJ----最少步数

最少步数

时间限制:3000 ms  |  内存限制:65535 KB
难度:4
描述

这有一个迷宫,有0~8行和0~8列:

 1,1,1,1,1,1,1,1,1
 1,0,0,1,0,0,1,0,1
 1,0,0,1,1,0,0,0,1
 1,0,1,0,1,1,0,1,1
 1,0,0,0,0,1,0,0,1
 1,1,0,1,0,1,0,0,1
 1,1,0,1,0,1,0,0,1
 1,1,0,1,0,0,0,0,1
 1,1,1,1,1,1,1,1,1

0表示道路,1表示墙。

现在输入一个道路的坐标作为起点,再如输入一个道路的坐标作为终点,问最少走几步才能从起点到达终点?

(注:一步是指从一坐标点走到其上下左右相邻坐标点,如:从(3,1)到(4,1)。)

输入
第一行输入一个整数n(0<n<=100),表示有n组测试数据;
随后n行,每行有四个整数a,b,c,d(0<=a,b,c,d<=8)分别表示起点的行、列,终点的行、列。
输出
输出最少走几步。
样例输入
2
3 1  5 7
3 1  6 7
样例输出
12
11
用dfs 或 bfs进行穷举
(1)DFS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <stdio.h>
#include <string.h>
#define INF 80
 
int res,flag[9][9];
int maze[9][9]={
 1,1,1,1,1,1,1,1,1,
 1,0,0,1,0,0,1,0,1,
 1,0,0,1,1,0,0,0,1,
 1,0,1,0,1,1,0,1,1,
 1,0,0,0,0,1,0,0,1,
 1,1,0,1,0,1,0,0,1,
 1,1,0,1,0,1,0,0,1,
 1,1,0,1,0,0,0,0,1,
 1,1,1,1,1,1,1,1,1 
};
 
void DFS(int si,int sj,int ei,int ej,int count){
    if(si==ei && sj==ej){
        if(count + 1 < res)
            res = count+1;
        return;
    }
    if(si<0 || si>8 || sj<0 || sj>8 || flag[si][sj] || maze[si][sj]) return;
    flag[si][sj]=1;
    // four corners
    if((si==0 || si==8) && ((sj==0 || sj==8))){
        int ssi,sssi,ssj,sssj;
        if(si==0 && sj==0){
            ssi=si+1,ssj=sj;
            sssi=si,sssj=sj+1;
        }
        else if(si==0 && sj==8){
            ssi=si+1,ssj=sj;
            sssi=si-1,sssj=sj;
        }
        else if(si==8 && sj==0){
            ssi=si-1,ssj=sj;
            sssi=si,sssj=sj+1;
        }
        else{
            ssi=si-1,ssj=sj;
            sssi=si,sssj=sj-1;
        }
        DFS(ssi,ssj,ei,ej,count+1);
        DFS(sssi,sssj,ei,ej,count+1);
    }
    //four edges
    else if(!(si>0 && si<8 && sj>0 && sj<8)){
        int ssi,ssj,sssi,sssj,ssssi,ssssj;
        if(si==0){
            ssi=si,ssj=sj-1;
            sssi=si,sssj=sj+1;
            ssssi=si+1,ssssj=sj;
        }
        else if(si==8){
            ssi=si,ssj=sj-1;
            sssi=si,sssj=sj+1;
            ssssi=si-1,ssssj=sj;
        }
        else if(sj==0){
            ssi=si,ssj=sj+1;
            sssi=si-1,sssj=sj;
            ssssi=si+1,ssssj=sj;
        }
        else{
            ssi=si-1,ssj=sj;
            sssi=si+1,sssj=sj;
            ssssi=si,ssssj=sj-1;
        }
        DFS(ssi,ssj,ei,ej,count+1);
        DFS(sssi,sssj,ei,ej,count+1);
        DFS(ssssi,ssssj,ei,ej,count+1);
    }
    else{
        DFS(si-1,sj,ei,ej,count+1);
        DFS(si+1,sj,ei,ej,count+1);
        DFS(si,sj-1,ei,ej,count+1);
        DFS(si,sj+1,ei,ej,count+1);
    }
    flag[si][sj]=0;
}
 
int main(){
    int n,si,sj,ei,ej;
    scanf("%d",&n);
    while(n--){
        scanf("%d%d%d%d",&si,&sj,&ei,&ej);
        res = INF;
        memset(flag,0,sizeof(flag));
        DFS(si,sj,ei,ej,-1);
        printf("%d\n",res);
    }
    return 0;
}

 (2)BFS

bfs求最小步数之所以不用更新距离d,是因为访问任何一个点(i,j)
必然都是距离(si,sj)最短距离(联想起bfs的分支图即明白这一点)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <cstdio>
#include <queue>
 
using namespace std;
 
typedef pair<int,int> P; //用结构体struct point{x,y}亦可
const int INF=80;
 
char maze[10][10]={ //用char更节约内存
 "111111111",
 "100100101",
 "100110001",
 "101011011",
 "100001001",
 "110101001",
 "110101001",
 "110100001",
 "111111111"
};
int sx,sy,gx,gy;
int d[9][9]; //出发点到(i,j)的最短路径,同时起到判断是否已访问的作用
int dis[4][2]={ //or 定义dx[4]&dy[4]
    1,0,
    0,1,
    -1,0,
    0,-1    
};
 
void Init(){
    int i,j;
    for(i=0;i<9;i++)
        for(j=0;j<9;j++)
            d[i][j]=INF;
}
 
void BFS(){
    queue <P> q;
    q.push(P(sx,sy));
    d[sx][sy]=0;
    while(q.size()){ //or !q.empty():仍有点未被访问
        P p=q.front();
        q.pop();
        if(p.first==gx && p.second==gy)
            break;
        int i=0;
        for(;i<4;i++){
            int x=p.first+dis[i][0],y=p.second+dis[i][1];
            if(x>=0 && x<=8 && y>=0 && y<=8
                && maze[x][y]=='0'
                && d[x][y]==INF){ //表示(x,y)暂未访问
                d[x][y]=d[p.first][p.second]+1;
                q.push(P(x,y));
            }
        }
    }
    printf("%d\n",d[gx][gy]);
}
 
int main(){
    int n;
    scanf("%d",&n);
    while(n--){
        scanf("%d%d%d%d",&sx,&sy,&gx,&gy);
        Init();
        BFS();
    }
    return 0;
}

对BFS的一点补充。。。

我们实际可以不用定义点,只要能够对不同的点进行区分即可,用9*i+j可将二维的点转化为一维(实际有点时间换空间的意味,全当另一种方法的了解),核心如下:

int graph[81],front,rear;front和rear共同起到队列的作用,入队,graph[rear++]=9*i+j(入队点为(i,j)),出队时,x=graph[front]/9,y=graph[front++]%9;

其余同BFS代码

其中,bfs的代码参照:http://blog.csdn.net/sevenmit/article/details/13168363

 

posted @   我在这儿  阅读(249)  评论(0编辑  收藏  举报
编辑推荐:
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· Linux系列:如何调试 malloc 的底层源码
阅读排行:
· C# 中比较实用的关键字,基础高频面试题!
· .NET 10 Preview 2 增强了 Blazor 和.NET MAUI
· Ollama系列05:Ollama API 使用指南
· 为什么AI教师难以实现
· 如何让低于1B参数的小型语言模型实现 100% 的准确率
历史上的今天:
2016-03-04 Hanoi塔

喜欢请打赏

扫描二维码打赏

了解更多

点击右上角即可分享
微信分享提示