题目描述
这天,小明在玩迷宫游戏。
迷宫为一个 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;
}
}