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,10表示道路,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#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的分支图即明白这一点)#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