nyoj最少步数_广搜.深搜.FloydWarshall

本文探讨了在特定迷宫中寻找从起点到终点的最短路径问题,使用广度优先搜索(BFS)和Floyd-Warshall算法两种方法进行解答,并提供了具体的Java和C++实现代码。

最少步数

时间限制: 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
来源
[苗栋栋]原创
上传者

苗栋栋


这道题有很多种做法,咱广搜写的不多(150ms),暂时只能这样啦。还可以用深搜(50ms),其中的区别这里有:http://blog.youkuaiyun.com/chao1983210400/article/details/21160245   这题其实就是求最短路径,用floyd-warshall算法也可以


import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class nyoj最小步数_广搜 {
   static int[][] c = {
	   {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}
   };
   static int[]dx = {-1,0,1,0};
   static int[]dy = {0,-1,0,1};
   static boolean [][]vis;
     static Queue<Integer> Q;
     static int x,y,Count=0;
     static int [][]dis ;
	public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int s,t;
            int T = sc.nextInt();
            while(T-->0){
            	s = sc.nextInt();
            	t = sc.nextInt();
            	x = sc.nextInt();
            	y = sc.nextInt();
            	vis = new boolean[9][9];
            	Q = new LinkedList<Integer>();Q.clear();
            	dis = new int[9][9];
            	bfs(s,t);
            	System.out.println(dis[x][y]);
            }
	}
	private static void bfs(int s0,int t0) {
	    int ps0,pt0;
		Q.add(s0*8+t0);
		while(!Q.isEmpty()){
			
			int a = Q.poll();
			ps0 = a/8; pt0 = a%8;
			if(ps0==x&&pt0==y)return ;
				
			vis[ps0][pt0] = true;
			for(int i=0; i<4; i++){
				
				  s0 = ps0+dx[i]; t0 = pt0+dy[i];
				    
					if(s0>=0&&s0<=8 && t0>=0&&t0<=8)
					if(!vis[s0][t0] && c[s0][t0]!=1){
						
						dis[s0][t0] = dis[ps0][pt0] +1; 
						if(s0==x&&t0==y)return ;
							
						vis[s0][t0]=true;
						Q.add(s0*8+t0);
					}
				}
			}
		}
	}

FloydWarshall算法

 
#include<iostream>
#include<cmath>
using namespace std;
int mz[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
};
inline int ABS(int a)
{
	return a>0?a:-a;
}
int len[10][10][10][10];
const int INF=100000;
void FloydWarshall()
{
	for(int i=1;i!=8;i++)
		for(int j=1;j!=8;j++)
			for(int k=1;k!=8;k++)
				for(int l=1;l!=8;l++)
					if(i==k && j== l) len[i][j][k][l]=0;
					else if(mz[i][j]==0 && mz[k][l]==0 && ABS(i-k)+ABS(j-l)==1) len[i][j][k][l]=1;
					else len[i][j][k][l]=INF;
	int v=49;
	for(int k=1;k!=8;k++)
		for(int l=1;l!=8;l++)
			for(int m=1;m!=8;m++)
				for(int n=1;n!=8;n++)
					for(int i=1;i!=8;i++)
						for(int j=0;j!=8;j++)
							if(len[m][n][i][j]>len[m][n][k][l]+len[k][l][i][j]) len[m][n][i][j]=len[m][n][k][l]+len[k][l][i][j];
}
int main()
{
	FloydWarshall();
	int n,a,b,c,d;
	cin>>n;
	while(n--)
	{
		cin>>a>>b>>c>>d;
		cout<<len[a][b][c][d]<<endl;
	}
}        




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值