P1979 [NOIP2013 提高组] 华容道

题目大意

详细题目传送门

\(n\times m\) 的华容道盘,有障碍。多组询问,每组障碍不变。其中要将初始在 \((sx,sy)\) 的棋子移动到 \((tx,ty)\)。初始空白的位置在 \((ex,ey)\)。求至少多少次移动完成目标,无法完成输出 -1

\(n,m\leq30,q\leq 500\)

思路

发现显然应该是要预处理什么东西然后对于每组询问再做。然后发现其实这个游戏就是用空格铺路让棋子按照合法的最短距离一步一步走。

手玩一下可以发现先按照最短距离将空格移动到初始位置之后就可以开始移动了。发现如果要移动一个棋子到一个方向就需要在不移动原棋子的情况下移动空格。

之后就可以写一个移动的函数了,用宽搜 \(f(cx,cy,sx,sy,ex,ey)\) 表示空格一开始在 \((sx,sy)\),在不经过 \((cx,cy)\) 时移动到 \((ex,ey)\) 的最短步数。

但是如果我们预处理出所有的 \(f\) 就可以以它为边权跑最短路就可以了。但是发现预处理的时间复杂度是 \(O(n^8)\) 的,无法接受。

观察到其实每一次的移动除了一开始移动空格到起点四周外只会在四个方向动。于是通过跑 \(f()\) 来算新的 \(v(x,y,a,b)\),其中 \(a,b\in[0,4)\) 表示四个方向。这样我们可以通过 \(T(16n^4)\) 的方法求助这个棋盘移动任意一个位置的步数。

发现对于每一组询问跑最短路即可。但是对于状态我设置的与普通最短路略有不同,设了 \(d(x,y,a),a\in[0,4)\) 表示目前在 \((x,y)\),空格在 \((x,y)\)\(a\) 方向时的最短步数即可。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN=30+5;
const ll MAXQ=500+5;
ll n,m,Q;
bool gd[MAXN][MAXN];
ll dx[]={0,0,1,-1},dy[]={1,-1,0,0};
bool cg(ll x,ll y){return x>0&&x<=n&&y>0&&y<=m&&gd[x][y];
}
bool vis[MAXN][MAXN];
struct node{ll x,y,tm;
};
ll bfs(ll cx,ll cy,ll sx,ll sy,ll ex,ll ey){queue<node>q;memset(vis,false,sizeof(vis));q.push({sx,sy,0});vis[sx][sy]=true;if(sx==cx&&sy==cy){return 1e9;}while(!q.empty()){ll x=q.front().x,y=q.front().y,tm=q.front().tm;q.pop();if(x==ex&&y==ey){return tm;}for(int i=0;i<4;++i){ll u=x+dx[i],v=y+dy[i];if(cg(u,v)&&!vis[u][v]&&!(u==cx&&v==cy)){vis[u][v]=true;q.push({u,v,tm+1});}}}return 1e9;
}
ll val[MAXN][MAXN][4][4];
struct State{ll qx,qy,lst,tm;bool operator<(const State&K)const{if(tm==K.tm){if(qx==K.qx){if(qy==K.qy){return lst<K.lst;}return qy<K.qy;}return qx<K.qx;}return tm>K.tm;}
};
bool vs[MAXN][MAXN][4];
ll dis[MAXN][MAXN][4];
void dijkstra(ll ex,ll ey,ll sx,ll sy,ll tx,ll ty){priority_queue<State>pq;memset(vs,false,sizeof(vs));memset(dis,0x3f,sizeof(dis));for(int i=0;i<4;++i){ll u=sx+dx[i],v=sy+dy[i];if(!cg(u,v)){continue;}ll w=bfs(sx,sy,ex,ey,u,v);if(w>=1e8){continue;}pq.push({sx,sy,i,w});dis[sx][sy][i]=w;}while(!pq.empty()){State sta=pq.top();pq.pop();ll x=sta.qx,y=sta.qy,lst=sta.lst;if(vs[x][y][lst]){continue;}vs[x][y][lst]=true;for(int i=0;i<4;++i){ll u=x+dx[i],v=y+dy[i];ll w=val[x][y][lst][i];if(w>1e8){continue;}ll nlst;if(i==0){nlst=1;}else if(i==1){nlst=0;}else if(i==2){nlst=3;}else{nlst=2;}if(dis[x][y][lst]+w+1<dis[u][v][nlst]){dis[u][v][nlst]=dis[x][y][lst]+w+1;pq.push({u,v,nlst,dis[u][v][nlst]});}}}
}
int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n>>m>>Q;for(int i=1;i<=n;++i){for(int j=1;j<=m;++j){cin>>gd[i][j];}}memset(val,0x3f,sizeof(val));for(int i=1;i<=n;++i){for(int j=1;j<=m;++j){if(!cg(i,j)){continue;}for(int k=0;k<4;++k){ll x=i+dx[k],y=j+dy[k];if(!cg(x,y)){continue;}for(int l=0;l<4;++l){if(k==l){val[i][j][k][l]=0;continue;}ll u=i+dx[l],v=j+dy[l];if(!cg(u,v)){continue;}val[i][j][k][l]=bfs(i,j,x,y,u,v);}}}}while(Q--){ll ex,ey,sx,sy,tx,ty;cin>>ex>>ey>>sx>>sy>>tx>>ty;if(sx==tx&&sy==ty){cout<<0<<endl;continue;}if(!cg(sx,sy)||!cg(tx,ty)){cout<<-1<<endl;continue;}dijkstra(ex,ey,sx,sy,tx,ty);ll ans=min({dis[tx][ty][0],dis[tx][ty][1],dis[tx][ty][2],dis[tx][ty][3]});if(ans>1e8){cout<<-1<<endl;}else{cout<<ans<<endl;}};return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/842829.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

responsively-lazy 可实现响应式图片懒加载的js插件

在线演示 下载 responsively-lazy是一款非常实用的可实现响应式图片懒加载的插件。它可以根据容器的大小来智能选择加载适合尺寸的图片,做到图片的响应式效果。并且使用它对于SEO是十分友好的。该图片懒加载插件的特点还有:响应式图片 不做任何不必要的请求 可以在任何支持…

简单实用的鼠标滑过图片遮罩层动画jQuery插件

nsHover是一款简单实用的鼠标滑过图片遮罩层动画 JQUERY插件。该插件可以在图片或块级元素上制作鼠标滑过时的遮罩层动画效果,它可以设置遮罩层的前景色和背景色,可以制作圆形图片等,非常实用。在线演示 下载使用方法 使用该鼠标滑过插件需要引入jQuery和ns.hover.min.js文…

2024web漏洞扫描神器xray安装及使用_2024-11-28

一、功能 开源的Web漏洞扫描工具,支持以下漏洞XSS漏洞检测 (key: xss) SQL 注入检测 (key: sqldet) 命令/代码注入检测 (key: cmd-injection) 目录枚举 (key: dirscan) 路径穿越检测 (key: path-traversal) XML 实体注入检测 (key: xxe) 文件上传检测 (key: upload) 弱口令检测…

Rocky9 挂载磁盘

查看系统磁盘情况 fdisk -l使用Parted工具为数据盘进行分区。 运行以下命令开始分区。 parted /dev/sdb 运行以下命令,设置GPT分区格式 mklabel gpt 运行以下命令,划分一个主分区,并设置分区的开始位置和结束位置 mkpart primary 1 100% 运行以下命令,检查分区是否对齐 ali…

精准医学 | Scipher Medicine开发的MSRC预测TNFi疗效不佳

#文献速递 #精准医学 #类风湿关节炎++++++++++++++++++1. Scipher Medicine在ACR2024的一篇投稿, 证实了一些人关于"TNFi处方量下降"的担心. 但是可以推测, 相关药监/各种医疗保险可能会高兴. 这也可能会激发我们的好奇心, 即有没有可能开发融合蛋白型TNFi的专用疗效…

VScode配置C语言环境

第一步下载VScode:Visual Studio Code - Code Editing. Redefined 第二步搜索下载VScode插件: ​ C/C++Chinese上面两个插件安装完成后会提示重启VScode完成中文语言设置 第三步配置C语言编译器:https://wwgn.lanzoul.com/iB4US2gj0ayh 密码:8y95 下载完成后解压,这里我选…

Free5GC源码研究(10) - SMF研究(上)

本文研究Session Management Function (SMF)的功能SMF的概念 对于free5gc各NF的研究来到了最终阶段,只剩SMF和AMF两个功能,是时候回顾一下TS23.501中的这几张网络架构图。首先是这一张经典的非漫游情境下各NF的交互架构:这张图里,核心网所有的NF通过SBI总线相连,本质上就…

jquery计数器动画特效

这是一款jquery计数器动画特效。该jquery计数器动画特效使用bootstrap网格系统进行布局,然后通过jQuery animate方法来制作炫酷的计数器动画特效。在线演示 下载使用方法 在页面中引入jquery,bootstrap.min.css和font-awsome.min.css文件。< link href="dist/boots…

小诚因为金铲铲D不到牌破产啦

小诚因为金铲铲D不到牌破产啦 Description 小诚和他身边的朋友最近好像出了点经济问题…… 已知小诚的人际关际网中包含 n* 个人(小诚也在其中),每个人手上现在有ai元,他们可以彼此之间互相借钱,他们只希望在最后手上恰好有 bi 元 众所周知,欠钱容易借钱难,没借到之前是…

代码精简之路-责任链模式

前言 常说c#、java是面向对象的语言,但我们平时都是在用面向过程的思维写代码,实现业务逻辑像记流水账一样,大篇if else的判断;对业务没有抽象提炼、代码没有分层。随着需求变化、功能逐步拓展、业务逻辑逐渐复杂;代码越来越长、if else嵌套越来越多,代码会变成程序员都厌…

vxe-table 使用表格多选数据、复选框多选

在 vxe-table 启用列多选功能,通过参数 column.type = checkbox 设置类型为多选类型就可以了。 官网:https://vxetable.cn<template><div><vxe-grid v-bind="gridOptions"></vxe-grid></div> </template><script> expor…

【QT】使用Qxlsx读取Excel单元格中函数表达式的结果值

【QT】使用Qxlsx读取Excel单元格中函数表达式的结果值 零、起因 是这样的,目前朋友托我写一款模板生成软件,任务是先把他写的程序文件复制一份出来,然后再根据Excel中对应位置的单元格的值,修改程序文件副本中的某些文件。对于读Excel的需求,经过测试,最终选择Qxlsx这款开…