NYOJ-0058-最少步数

最少步数

时间限制: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

思路:

  1. 我采用的是广度搜索,起点步数,标记为0,以后每向周围走一步,到达的地方标记就+1;

  2. 由于矩阵(即地图)题目已给出,而且给了边界全为1,因此不用再设边界

#include 
#include 
#include 
using namespace std;

struct Node {		//点集
	int x;			//横坐标
	int y;			//纵坐标
} s,e,r,z;		//起点s,终点e,当前点z

int m[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 }
};

int dp[9][9];		//记录下从起点到当前点的最小步数
int x1,y1,x2,y2;	//起始和终止坐标
queue MG;		//广搜辅助队列

void BFS( Node x ) {		//广度搜索
	z = MG.front();
//	printf( "x=%d\ty=%d\t%3d\n",z.x,z.y,dp[z.x][z.y] );
	MG.pop();
	if( z.x==x2 && z.y==y2 )           //到达终点后返回
		return ;
	for( int i=z.x-1 ; i<=z.x+1 ; i++ )//前后左右四个方向第一个元素
	{
		for( int j=z.y-1 ; j<=z.y+1 ; j++ ) {
		    //排除四个顶点
			if( ( i==z.x-1 && j==z.y-1 ) || ( i==z.x+1 && j==z.y+1 )        
			        || ( i==z.x-1 && j==z.y+1 ) || ( i==z.x+1 && j==z.y-1 ) )
				continue ;
			if( !m[i][j] && dp[i][j]==-1 ) {    //-1表示未经过
				r.x = i;
				r.y = j;
				dp[i][j] = dp[z.x][z.y]+1 ;     //每走一步步数+1
				MG.push(r);                     //符合要求的该点进入队列
			}
		}
//		printf("\n");
	}
	if( !MG.empty() )
		BFS( MG.front() );
	return ;
}

int main() {
	int t;
	scanf( "%d",&t );
	while( t-- ) {
		memset( dp , -1 , sizeof(dp) );         //初始化为-1,同时表示未经过
		scanf( "%d%d%d%d",&x1,&y1,&x2,&y2 );
		s.x = x1;
		s.y = y1;
		MG.push( s );                           //起点进入队列
		dp[x1][y1]=0;
		BFS( MG.front() ) ;                     //开始广度搜索
		printf( "%d\n",dp[x2][y2] );            //输出步数
/*		for( int i=0 ; i<9 ; i++) {
			for( int j=0 ; j<9 ; j++ )
				printf( "%3d ",dp[i][j] );
			printf("\n");
		}*/
		while( !MG.empty() ) {
			MG.pop();
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值