蓝桥杯2022年第十三届决赛真题-迷宫

题目描述

这天,小明在玩迷宫游戏。

迷宫为一个 n × n 的网格图,小明可以在格子中移动,左上角为 (1, 1),右下角 (n, n) 为终点。迷宫中除了可以向上下左右四个方向移动一格以外,还有 m 个双向传送门可以使用,传送门可以连接两个任意格子。

假如小明处在格子 (x1, y1),同时有一个传送门连接了格子 (x1, y1) 和 (x2, y2),那么小明既可以花费 1 的步数向上下左右四个方向之一走一格 (不能越过边界),也可以花费 1 的步数通过传送门走到格子 (x2, y2) 去。

而对于同一个迷宫,小明每次进入的初始格子是在这 n × n 个格子中均匀随机的 (当然运气好可以直接随机到终点),他想知道从初始格子走到终点的最短步数的期望值是多少。

输入格式

输入共 1 + m 行,第一行为两个正整数 n, m。

后面 m 行,每行四个正整数 xi1, yi1, xi2, yi2 表示第 i 个传送门连接的两个格子坐标。

输出格式

输出共一行,一个浮点数表示答案 (请保留两位小数)。

样例输入

2 1
1 1 2 2

样例输出

0.75

思路:一看就是搜索题,一开始想的是用深搜,写个循环,依次查找每个点到终点的步数,然后相加求结果,结果说什么killed,很懵逼,然后开始想法剪枝,若搜索过程中,该次搜索的步数大于之前搜索到终点的最小值还大,那就终止,结果还是错。而且用深搜的时候还遇到了map.containsKey错误的情况,原因是map里存了自己定义的类,要重写hashCode()和equals()方法。
然后想到了反向广搜,起始点为终点,然后向其他点走,走到某个点的步数就是该点到终点的步数,注意,这样搜索必然是最短路径,因为BFS有最短路效应。
然后写了一发还是错,又想到了,某个点的传送门不一定是唯一的。
所以最后用Map<Integer,List<int[]>>存一下传送门的位置。终于ac.

DFS错误代码

import java.util.*;

public class Main {
	static int N = 200005;
	static int mod = 1000000007;
	static int[]dp = new int [N];
	static char[][] str = new char[1005][1005];
	static int vis[][] = new int [2005][2005];
	static int cnt=1;
	static int n=0;
	static double sum=0;
	static double res = 9999999;
	static int a[][] = new int[2005][2005];
	static Map<node,node> map = new HashMap<>();
	static int dirx[] ={-1,0,1,0};
	static int diry[] ={0,1,0,-1};
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		int m = sc.nextInt();
		for(int i=0;i<m;i++){
			int x1 = sc.nextInt();
			int y1 = sc.nextInt();
			int x2 = sc.nextInt();
			int y2 = sc.nextInt();
			map.put(new node(x1,y1),new node(x2,y2));
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				dfs(i,j,0);
				sum+=res;
				//System.out.println(res);
				res=9999999;
			}
		}
		System.out.println(String.format("%.2f",sum/(n*n)));
		sc.close();
	}

	public static void dfs(int x,int y,double cnt){
		if(x==n&&y==n){
			res = Math.min(res,cnt);
			return;
		}
		vis[x][y]=1;
		if(map.containsKey(new node(x,y))){
			node temp = map.get(new node(x,y));
			dfs(temp.x,temp.y,cnt+1);
		}
		for(int i=0;i<4;i++){
			int nx=x+dirx[i];
			int ny=y+diry[i];
			if(vis[nx][ny]==0&&nx>0&&nx<=n&&ny>0&&ny<=n){
				dfs(nx,ny,cnt+1);
			}
		}
		vis[x][y]=0;
	}
}
class node{
	int x;
	int y;
	public node() {
	}
	public node(int x, int y) {
		this.x = x;
		this.y = y;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		node other = (node) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}
	
}

BFS正确代码

import java.util.*;

public class Main {
	static int N = 200005;
	static int mod = 1000000007;
	static int[]dp = new int [N];
	static char[][] str = new char[1005][1005];
	static int vis[][] = new int [2005][2005];
	static int cnt=1;
	static int n=0;
	static double sum=0;
	static double res = 9999999;
	static int a[][] = new int[2005][2005];
	static Map<Integer,List<int[]>> map = new HashMap<>();
	static int b[][] = new int[2005][2005];
	static int dirx[] ={-1,0,1,0};
	static int diry[] ={0,1,0,-1};
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		int m = sc.nextInt();
		for(int i=0;i<m;i++){
			int x1 = sc.nextInt();
			int y1 = sc.nextInt();
			int x2 = sc.nextInt();
			int y2 = sc.nextInt();
			if(!map.containsKey(x1*n+y1)){
				map.put(x1*n+y1,new ArrayList<>());
			}
			map.get(x1*n+y1).add(new int[]{x2,y2});

			if(!map.containsKey(x2*n+y2)){
				map.put(x2*n+y2,new ArrayList<>());
			}
			map.get(x2*n+y2).add(new int[]{x1,y1});
		}
		LinkedList<node>q = new LinkedList<>();
		q.offer(new node(n,n,0));
		while(!q.isEmpty()){
			node temp = q.peek();
			q.remove();
			if(map.containsKey(temp.x*n+temp.y)){
				List<int[]> list = map.get(temp.x*n+temp.y);
					for(int i=0;i<list.size();i++){
						int[] t = list.get(i);
						if(a[t[0]][t[1]]==0){
							a[t[0]][t[1]]=temp.step+1;
							q.offer(new node(t[0],t[1],a[t[0]][t[1]]));
						}
				}
			}
			for(int i=0;i<4;i++){
				int nx = temp.x+dirx[i];
				int ny = temp.y+diry[i];
				if(a[nx][ny]==0&&nx>0&&nx<=n&&ny>0&&ny<=n){
					a[nx][ny]=temp.step+1;
					q.offer(new node(nx,ny,a[nx][ny]));
				}
			}
		}
		a[n][n]=0;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				//System.out.print(a[i][j]);
				sum+=a[i][j];
			}
			//System.out.println();
		}
		System.out.println(String.format("%.2f",sum/(n*n)));
		sc.close();
	}

	public static void dfs(int x,int y,double cnt){
		if(cnt>res){
			return;
		}
		if(x==n&&y==n){
			res = Math.min(res,cnt);
			return;
		}
		vis[x][y]=1;
		if(b[x][y]!=0){
			int nx = b[x][y]/n;
			int ny = b[x][y]%n;
			if(ny==0){
				nx--;
				ny=n;
			}
			dfs(nx,ny,cnt+1);
		}
		for(int i=0;i<4;i++){
			int nx=x+dirx[i];
			int ny=y+diry[i];
			if(vis[nx][ny]==0&&nx>0&&nx<=n&&ny>0&&ny<=n){
				dfs(nx,ny,cnt+1);
			}
		}
		vis[x][y]=0;
	}
}
class node{
	int x;
	int y;
	int step;
	public node() {
	}
	public node(int x, int y, int step) {
		this.x = x;
		this.y = y;
		this.step = step;
	}
	
	
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值