最少步数

时间限制: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
#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("%dn",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("%dn",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

 

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!