迷宫 蓝桥杯

问题描述

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

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

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

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

输入格式

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

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

输出格式

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

样例输入

复制代码
2 1
1 1 2 2 

样例输出

复制代码
0.75

反向搜索 只要搜一次就行

另外本题不标记 因为传送门会使之前的结果不一定是最优的。增加了空间复杂度。

复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define fp(i,a,b) for(int i=a;i<=b;++i)
#define PII pair<int,int>
const int N=2e3+10;
const int mod=1e9+7;
const double eps=1e-5;
typedef double db;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int n,m;
int dist[N][N];
vector<PII>door[N][N];
bool is_door[N][N];
void bfs()
{    
    memset(dist,0x3f,sizeof dist);
    dist[n][n]=0;
    queue<PII>q;
    q.push({n,n});
    
    while(q.size())
    {
        auto t=q.front();
        q.pop();
        
        for(int p=0;p<4;p++)
        {
            int X=dx[p]+t.first,Y=dy[p]+t.second;
            if(X<1||X>n||Y<1||Y>n) continue;
            
            if(dist[X][Y]>dist[t.first][t.second]+1)
            {
                dist[X][Y]=dist[t.first][t.second]+1;
                q.push({X,Y});
            }
            if(is_door[t.first][t.second])//如果当前点可以使用传送门 
            {
                //因为是反向搜图,可以多对一
                for(auto s:door[t.first][t.second])
                {
                    //取出里面的点
                    if(dist[s.first][s.second]>dist[t.first][t.second]+1)
                    {
                        dist[s.first][s.second]=dist[t.first][t.second]+1;
                        q.push({s.first,s.second});
                    } 
                } 
            }
            
        }
    } 
} 
signed main()
{
   cin>>n>>m;
   
   for(int i=1;i<=m;i++)
   {
   	  int a,b,c,d;
   	  cin>>a>>b>>c>>d;
   	  door[a][b].push_back({c,d});
      door[c][d].push_back({a,b});
      is_door[a][b]=is_door[c][d]=true;
   }
   bfs();
   int sum=0;
   for(int i=1;i<=n;i++)
   {
   	  for(int j=1;j<=n;j++)
   	  {
   	     sum+=dist[i][j];	
	  }
   }
   cout<<fixed<<setprecision(2)<<1.0*sum/(n*n)<<"\n";
    
	return 0;
} 
相关推荐
芬加达3 分钟前
leetcode34
java·数据结构·算法
资深web全栈开发21 分钟前
LeetCode 1015. 可被 K 整除的最小整数 - 数学推导与鸽巢原理
算法·leetcode·职场和发展
dragoooon3441 分钟前
[优选算法专题八.分治-归并 ——NO.46~48 归并排序 、数组中的逆序对、计算右侧小于当前元素的个数]
数据结构·算法·排序算法·分治
CoderYanger41 分钟前
优选算法-队列+宽搜(BFS):72.二叉树的最大宽度
java·开发语言·算法·leetcode·职场和发展·宽度优先·1024程序员节
招摇的一半月亮1 小时前
P2242 公路维修问题
数据结构·c++·算法
星轨初途1 小时前
数据结构排序算法详解(5)——非比较函数:计数排序(鸽巢原理)及排序算法复杂度和稳定性分析
c语言·开发语言·数据结构·经验分享·笔记·算法·排序算法
人类发明了工具1 小时前
【机器人-激光雷达】点云时间运动补偿
算法·机器人
north_eagle2 小时前
向量搜索技术深度研究报告:架构原理、核心算法与企业级应用范式
算法·架构
椰萝Yerosius3 小时前
[题解]2024CCPC郑州站——Z-order Curve
c++·算法