loj2613 「NOIP2013」华容道[最短路]
感觉和以前做过的一个推箱子很像,都是可以用bfs解决的,而且都是手玩出结论。
因为起始棋子肯定是要和空格交换的,所以第一件事是先把空格移到棋子旁边。然后讨论怎么设计搜索状态。由于和推箱子实在太像了,所以直接借鉴,发现空格总是要贴着棋子走的要不然就是换个贴的方向继续走(这里的走就是指交换)。于是绑定两者,设计状态$f_{i,j,dir}$表示在棋子在某个格子,空格在上下左右四方位时候的最小移动次数。显然可以暴力bfs跑,但是这样没有经过优化,效率不高,实际上只要把它改的像最短路算法一点就行了,比如套个dijkstra,把每种状态和他可以推到的下一步状态(分为交换,或者空格跑到另一侧,这个的步数可以提前预处理)之间连边,边权即步数,这样建个图之后就是最短路了,起点有4个,终点有4个,$O(Qn^2\text{log}n^2)$,避免了bfs庞大的搜索树。
然后注意一个很容易忽略的细节。。我第一发就是这么挂掉的。。起点和终点在同一个位置要特判,不然会加上空格到起点的距离然后跪好多点。
code可能是我有史以来写过的最丑的,一堆循环展开。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define dbg(x) cerr << #x << " = " << x <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=+,INF=0x3f3f3f3f;
int mp[N][N],f[N][N][][],id[N][N][],cnt;
int n,m,Q,hx,hy,sx,sy,tx,ty;
int qx[],qy[],dis[N][N],l,r;
inline void bfs_step(int x,int y){
memset(dis,0x3f,sizeof dis);qx[l=r=]=x,qy[]=y,dis[x][y]=;
while(l<=r){
int i=qx[l],j=qy[l++];
if(!mp[i-][j]&&MIN(dis[i-][j],dis[i][j]+))qx[++r]=i-,qy[r]=j;
if(!mp[i+][j]&&MIN(dis[i+][j],dis[i][j]+))qx[++r]=i+,qy[r]=j;
if(!mp[i][j-]&&MIN(dis[i][j-],dis[i][j]+))qx[++r]=i,qy[r]=j-;
if(!mp[i][j+]&&MIN(dis[i][j+],dis[i][j]+))qx[++r]=i,qy[r]=j+;
}
}
struct thxorz{int to,nxt,w;}G[];
int Head[],tot;
inline void Addedge(int x,int y,int z){
G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot,G[tot].w=z;
G[++tot].to=x,G[tot].nxt=Head[y],Head[y]=tot,G[tot].w=z;
}
int dist[];
priority_queue<pii,vector<pii>,greater<pii> > q;
#define y G[j].to
inline void dij(int xx,int yy){
memset(dist,0x3f,sizeof dist);
if(id[xx][yy][])q.push(make_pair(dist[id[xx][yy][]]=dis[xx-][yy],id[xx][yy][]));
if(id[xx][yy][])q.push(make_pair(dist[id[xx][yy][]]=dis[xx][yy+],id[xx][yy][]));
if(id[xx][yy][])q.push(make_pair(dist[id[xx][yy][]]=dis[xx+][yy],id[xx][yy][]));
if(id[xx][yy][])q.push(make_pair(dist[id[xx][yy][]]=dis[xx][yy-],id[xx][yy][]));
while(!q.empty()){
int x=q.top().second,d=q.top().first;q.pop();
if(dist[x]^d)continue;
for(register int j=Head[x];j;j=G[j].nxt)if(MIN(dist[y],d+G[j].w))q.push(make_pair(dist[y],y));
}
}
#undef y
int main(){//freopen("test.in","r",stdin);freopen("test.ans","w",stdout);
read(n),read(m),read(Q);memset(mp,0x3f,sizeof mp);
for(register int i=;i<=n;++i)for(register int j=;j<=m;++j)read(mp[i][j]),mp[i][j]^=;
for(register int i=;i<=n;++i)for(register int j=;j<=m;++j)if(!mp[i][j]){
mp[i][j]=;
if(!mp[i-][j])bfs_step(i-,j),f[i][j][][]=dis[i][j+],f[i][j][][]=dis[i+][j],f[i][j][][]=dis[i][j-],id[i][j][]=++cnt;
if(!mp[i][j+])bfs_step(i,j+),f[i][j][][]=dis[i-][j],f[i][j][][]=dis[i+][j],f[i][j][][]=dis[i][j-],id[i][j][]=++cnt;
if(!mp[i+][j])bfs_step(i+,j),f[i][j][][]=dis[i-][j],f[i][j][][]=dis[i][j+],f[i][j][][]=dis[i][j-],id[i][j][]=++cnt;
if(!mp[i][j-])bfs_step(i,j-),f[i][j][][]=dis[i-][j],f[i][j][][]=dis[i][j+],f[i][j][][]=dis[i+][j],id[i][j][]=++cnt;
mp[i][j]=;
}
for(register int i=;i<=n;++i)for(register int j=;j<=m;++j)if(!mp[i][j]){
for(register int thx=;thx<;++thx)for(register int orz=;orz<;++orz)
if(orz^thx&&id[i][j][thx]&&id[i][j][orz])Addedge(id[i][j][thx],id[i][j][orz],f[i][j][thx][orz]);
if(id[i][j][])Addedge(id[i][j][],id[i-][j][],);
if(id[i][j][])Addedge(id[i][j][],id[i][j-][],);
}
while(Q--){
read(hx),read(hy),read(sx),read(sy),read(tx),read(ty);
if(sx==tx&&sy==ty){puts("");continue;}
mp[sx][sy]=;bfs_step(hx,hy);mp[sx][sy]=;
dij(sx,sy);
int tmp=_min(dist[id[tx][ty][]],_min(dist[id[tx][ty][]],_min(dist[id[tx][ty][]],dist[id[tx][ty][]])));
printf("%d\n",tmp<INF?tmp:-);
}
return ;
}
总结:棋盘类问题求最小解有常用方法就是最短路建模,注意考虑状态设计有效性,必要时跑分层图。
loj2613 「NOIP2013」华容道[最短路]的更多相关文章
- 「NOIP2013」华容道
		传送门 Luogu 解题思路 预支一点东西: 这题其实有着更为思维的图模型,还十分考验码力,不简单啊 这居然是联赛题 讲正解: 显然我们对于一种合法方案,空格子肯定是一直围绕着特定棋子反复横跳的. 所 ... 
- 「NOIP2013」「LuoguP1967」货车运输(最大生成树 倍增 LCA
		题目描述 AA国有nn座城市,编号从 11到nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最 ... 
- LG1983 「NOIP2013」车站分级  拓扑排序
		问题描述 LG1983 题解 考虑建立有向边\((a,b)\),代表\(a\)比\(b\)低级. 于是枚举每一辆车次经过的车站\(x \in [l,r]\),如果不是车辆停靠的车站,则从\(x\)向每 ... 
- 「NOIP2013」货车运输
		传送门 Luogu 解题思路 首先 \(\text{Kruskal}\) 一下,构造出一棵森林. 并查集还要用来判断连通性. 倍增 \(\text{LCA}\) 的时候顺便维护一下路径最小值即可. 细 ... 
- 「bzoj1003」「ZJOI2006」物流运输  最短路+区间dp
		「bzoj1003」「ZJOI2006」物流运输---------------------------------------------------------------------------- ... 
- 2090. 「ZJOI2016」旅行者 分治,最短路
		2090. 「ZJOI2016」旅行者 链接 loj 思路 \((l,mid)(mid+1,r)\).考虑跨过mid的贡献. 假设选的中间那条线的点为gzy,贡献为\(dis(x,gzy)+dis(g ... 
- 「BZOJ3694」「FJ2014集训」最短路
		「BZOJ3694」「FJ2014集训」最短路 首先树剖没得说了,这里说一下并查集的做法, 对于一条非树边,它会影响的点就只有u(i),v(i)到lca,对于lca-v的路径上所有点x,都可通过1-t ... 
- 「luogu4366」最短路
		「luogu4366」最短路 传送门 直接连边显然不行,考虑优化. 根据异或的结合律和交换律等优秀性质,我们每次只让当前点向只有一位之别的另一个点连边,然后就直接跑最短路. 注意点数会很多,所以用配对 ... 
- 「ZJOI2016」解题报告
		「ZJOI2016」解题报告 我大浙的省选题真是超级神仙--这套已经算是比较可做的了. 「ZJOI2016」旅行者 神仙分治题. 对于一个矩形,每次我们从最长边切开,最短边不会超过 \(\sqrt{n ... 
随机推荐
- 菜鸟系列docker——搭建私有仓库harbor(6)
			docker 搭建私有仓库harbor 1. 准备条件 安装docker sudo yum update sudo yum install -y yum-utils device-mapper-per ... 
- VIM 介绍
			gedit a.txt 是一个图形界面的文本编辑器. 需要安装图形界面才会有. nano a.txt 也是一样的 vi 是一种文本界面的编辑器. vim 是 vimsual interfa ... 
- php学习历程1——注册、登录(面向过程、面向对象)
			首先放一张天空之城 Php入门来的第一个小项目,首先做的是一个简陋的文章管理系统.有登录.注册.文章list.添加文章.修改文章.删除文章.分页这几个小功能. 面向过程的编码 面向对象的编码 首先做的 ... 
- python------模块基础【第二部分-time】------
			一.time UTC/GMT:世界时间 本地时间:本地时区时间 python中时间日期格式化符号: %y 两位数的年份表示(00-99) %Y 四位数的年份表示(000-9999) %m 月份(01- ... 
- django  F与Q查询  事务 only与defer
			F与Q 查询 class Product(models.Model): name = models.CharField(max_length=32) #都是类实例化出来的对象 price = mode ... 
- import xxx和from xxx import xx中修改被导入模块里面的变量的坑
			现在有如下几个模块: A.py 功能:定义全局变量,供其他模块使用 name = "张三" lists = [1, 2, 3, 4, 5] B.py 功能:打印A.py中的变量 f ... 
- 简单说说utf-8编码格式
			提到utf-8,脑海里立马出现了Unicode.那什么是utf-8, 什么是Unicode呢?简要说一下. Unicode(Universal Multiple-Octet Coded Charact ... 
- spring 的工厂类
			spring 的工厂类 1. 工厂类 BeanFactory 和 ApplicationContext 的区别. ApplicationContext 是 BeanFactory 的子接口,提供了比父 ... 
- 怎样创建并使用 vue 组件 (component) ?
			组件化开发 需要使用到组件, 围绕组件, Vue 提供了一系列功能方法, 这里仅记录组件的 最简单 的使用方法. 1. 通过 Vue.component(tagName, options) 注册一个 ... 
- 怎样修改输入框 placehoder 提示文本的颜色?
			1. 在这个问题上, 不同浏览器的设置方法有所差异, 可以写成下面这种形式. ::-webkit-input-placeholder { /* WebKit browsers */ color: #9 ... 
