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 ...
随机推荐
- iterm 2快捷键
快捷键 作用说明 command + f 搜索&查找,如果输入搜索内容后,按下 tab 键,就会 iTerm 自动帮选中搜索关键词,并且自动的帮我们复制到了剪贴板中.如果输入的是 shift+ ...
- pramfs理论
一.文件系统 1.百度百科: http://baike.baidu.com/link?url=WE3aLsszfbZZIPK-Vz8yPd799_RMqyfQZ4D-ETS5yd1nI8XzPK660 ...
- Linux特殊权限位suid、sgid深度详细及实践
特殊权限位基本说明: Linux系统基本权限位为9位权限,但还有额外3位权限位,共12位权限: suid s(有x) S 4 用户对应的权限位(用户对应的3位上) sgid ...
- (模板)luoguP3806(树上点分治模板题)
点分治的写法1: 题目链接:https://www.luogu.org/problem/P3806 题意:给出一颗带边权的树,结点数n<=1e4,每条边有权值<=1e4,有m组询问(m&l ...
- [转帖]方正数码发布基于龙芯3A3000系列整机
方正数码发布基于龙芯3A3000系列整机 http://www.loongson.cn/news/company/730.html 方正数码也出过龙芯相关的服务器和PC笔记本等 发布时间:2019-0 ...
- dij 费用流
#include <bits/stdc++.h> using namespace std; typedef long long lld; const int MAXN = 50010, M ...
- [读书笔记]Hadoop权威指南 第3版
下面归纳概述了用于设置MapReduce作业输出的压缩格式的配置属性.如果MapReduce驱动使用了Tool接口,则可以通过命令行将这些属性传递给程序,这比通过程序代码来修改压缩属性更加简便. Ma ...
- 并不对劲的CF1237D&E:Balanced Playlist and Binary Search Trees
CF1237D Balanced Playlist 题意 有一个长度为\(n\)(\(n\leq 10^5\))的循环播放歌单,每首歌有一个优秀值\(a_i\)(\(a_i\leq 10^9\)). ...
- mybatis调用java类
在mybatis的映射xml文件调用java类的方法: 使用的是OGNL表达式,表达式格式为:${@prefix@methodName(传递参数名称)} 1.如下代码所示:方法必须为静态方法:以下我只 ...
- java——ArrayList中contains()方法中的疑问
问题引子: ist<Student> students=new ArrayList<Student>(); students.add(new Student("201 ...