nyoj 58 最少步数

最少步数

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

[苗栋栋]原创

emmmm...刚开始用到时广搜,因为看到了最小值,因为深搜一般是用于找所有解,而广搜是用于找单一的最短路径,但是这道题也可以用深搜找出所有解,然后判断当前已经找到的路径所走的步数是否比当前已经找到的最小步数小,然后最后返回最小值

#include<stdio.h>
#include<string.h>
int min=99999;
int map[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 visit[9][9];
struct Node{
	int s,e,step;
}start,end;
int dfs(int x,int y,int step){
	if(x==end.s&&y==end.e){
		if(step<=min){
			min=step;
		}
	}
	if(x-1>=0&&visit[x-1][y]==0&&map[x-1][y]==0){
		visit[x-1][y]=1;
		dfs(x-1,y,step+1);//向上搜索 
		visit[x-1][y]=0;
	}
	if(x+1<9&&visit[x+1][y]==0&&map[x+1][y]==0){
		visit[x+1][y]=1;
		dfs(x+1,y,step+1);//向下搜索
		visit[x+1][y]=0;
	}
	if(y-1>=0&&visit[x][y-1]==0&&map[x][y-1]==0){
		visit[x][y-1]=1;
		dfs(x,y-1,step+1);//左搜 
		visit[x][y-1]=0;
	}
	if(y+1<9&&visit[x][y+1]==0&&map[x][y+1]==0){
		visit[x][y+1]=1;
		dfs(x,y+1,step+1);//右搜 
		visit[x][y+1]=0; 
	}
	return min;
}
int main(){
	int n;
	scanf("%d",&n);
	while(n--){
		min=99999;
		memset(visit,0,sizeof(visit));
		scanf("%d %d %d %d",&start.s,&start.e,&end.s,&end.e);
		printf("%d\n",dfs(start.s,start.e,0)); 
	}
	return 0;
}

找了一下广搜的解法,调试了一下自己的

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//方向,分别表示向上向下,向左向右
int map[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 visit[9][9];//标记
struct Node{
	int s,e,step;//记录当前坐标和走到此坐标下需要的步数
}start,end;
int bfs(int x,int y){
	queue<Node>q;
	Node a,b;
	a.s=x;
	a.e=y;
	a.step=0;
	q.push(a);
	while(!q.empty()){
		a=q.front();
		if(a.s==end.s&&a.e==end.e){
			return a.step;//因为广搜是非递归的,所以找到值直接返回就行了
		}
		q.pop();
		for(int i=0;i<4;i++){//对应四个方向
			b=a; 
			b.s+=dir[i][0];
			b.e+=dir[i][1];
			if(!map[b.s][b.e]&&!visit[b.s][b.e]&&b.s>=0&&b.e>=0&&b.s<9&&b.e<9){
				visit[b.s][b.e]=1;
				b.step=a.step+1;
				q.push(b);
			}
		}
	}
}
int main(){
	int n;
	scanf("%d",&n);
	while(n--){
		memset(visit,0,sizeof(visit));
		scanf("%d %d %d %d",&start.s,&start.e,&end.s,&end.e);
		printf("%d\n",bfs(start.s,start.e));
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值