NOIP2013 华容道

图论好题。 介于网上全是些令蒟蒻头昏的题解和排版一塌糊涂以及过于详细的题解。。。蒟蒻记录一下。。

显然需要将白格移动到 \(s\) 相邻格,然后交换 \(s\) 与白格,再将白格移动到 \(s\) 相邻格,然后交换 \(s\) 与白格……最后一步将白格移动到 与 \(s\) 相邻的 \(t\) ,交换白格与 \(s\)。

我们考虑到,将格子 \(a\) 从 \((i,j)\) 移动到相邻的格子 \(b\),需要让白格先移动到 \(b\),之后交换 \(a\) 与白格。显然 \(a\) 下一步还是要继续往其他方向移动的,所以白格仍然需要移动到格子 \(a\) 的某个相邻格。

我们写了一个 bfs ,可以在白格在 \((ei,ej)\), s \((si,sj)\) 的时候处理一些值,接下来详细阐述。


现在所阐述的 bfs 是在代码中 \(k=0,1,2,3\) 时的 bfs ,用于预处理建图。

设置状态 \((i,j,k)\) 表示 格子 \(s\) 在 \((i,j)\) ,白格在 \((i,j)\) 的方向 \(k\) 处。( \(k\) : left right up down,用0,1,2,3表示)。

可以通过 bfs 计算出 状态 \((i,j,k)\) 时, 白格开始移动,移动到棋盘上任意一个格子 \((x,y)\) 的花费 \(dis_{x,y}\)。注意,在代码中,为了方便标记哪些是不可能移动到的点,将所有 \(dis_{x,y}\) 都加一了,但在题解中 \(dis_{x,y}\) 仍然是原先的值。

从状态 \((i,j,k)\) 转移到另一个状态,有两种情况。

  • 白格与 \(s\) 交换,在状态 \((si,sj,k)\) 与 \((ei,ej,k\and 1)\) 之间连边 1。
  • 白格移动到了一个与 \(s\) 相邻的位置 \((xx,yy)\) ,在状态 \((si,sj,k)\) 与状态 \((si,sj,i)\) 之间连边 \(dis_{xx,yy}\).

如果要计算状态 \((x1,y1,k1)\) 到状态 \((x2,y2,k2)\) 之间的最小花费,只需要跑最短路即可。

也就是说,我们把状态作为点,花费作为边建图。


现在阐述的是在代码中 \(k=4\) 时的 bfs,这是处理 白格到 初始格的相邻格 花费的 bfs。

仍然先处理出所有的 \(dis_{x,y}\) , 意义与求法同 \(k=0,1,2,3\) 时一样。将与 \(s\) 相邻格的 \(dis_{x,y}\) 赋值在 dist 上。

最后计算答案,只需要 spfa 计算 \((tx,ty,0/1/2/3)\) 到 \((sx,sy,0/1/2/3)\) 的最短路。

#include<bits/stdc++.h>
using namespace std;
const int N=35,M=4010;
int n,m,q,mp[N][N],dis[N][N],dist[M];
bool vis[M];
int e,to[M*5],nxt[M*5],val[M*5],hd[M];
int dx[5]={-1,1,0,0};
int dy[5]={0,0,-1,1};
void add(int x,int y,int w){ to[++e]=y; nxt[e]=hd[x]; val[e]=w; hd[x]=e; }
void bfs(int ei,int ej,int si,int sj,int dir){
memset(dis,0,sizeof(dis));
queue<pair<int,int> >q;
q.push(make_pair(ei,ej)); dis[ei][ej]=1;
while(!q.empty()){
pair<int,int>w=q.front(); q.pop();
int x=w.first,y=w.second;
for(int i=0;i<4;i++){
int xx=x+dx[i],yy=y+dy[i];
if(!mp[xx][yy]||dis[xx][yy]||xx==si&&yy==sj) continue;
dis[xx][yy]=dis[x][y]+1; q.push(make_pair(xx,yy));
}
}//白格向外疯狂移动处理步数
if(dir==4) return; for(int i=0;i<4;i++){
int xx=si+dx[i],yy=sj+dy[i];
if((xx==ei&&yy==ej)||!dis[xx][yy]) continue;
add(si*30*4+sj*4+dir,si*30*4+sj*4+i,dis[xx][yy]-1);//白格移动
}
add(si*30*4+sj*4+dir,ei*30*4+ej*4+(dir^1),1);//交换
return;
}
void spfa(int x,int y){
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis)); queue<int>q;
for(int i=0;i<4;i++){
if(!dis[x+dx[i]][y+dy[i]]) continue;
int id=x*30*4+y*4+i; q.push(id);
dist[id]=dis[x+dx[i]][y+dy[i]]-1; vis[id]=1;
}
while(!q.empty()){
int id=q.front(); q.pop(); vis[id]=0;
// cout<<id<<endl;
for(int i=hd[id];i;i=nxt[i]){
int nxid=to[i],nxval=val[i];
// cout<<"nxid: "<<nxid<<endl;
if(dist[nxid]>dist[id]+nxval){
dist[nxid]=dist[id]+nxval;
if(vis[nxid]) continue;
vis[nxid]=1; q.push(nxid);
}
}
}
return;
}
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&mp[i][j]);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(!mp[i][j]) continue;
if(mp[i-1][j]) bfs(i-1,j,i,j,0);
if(mp[i+1][j]) bfs(i+1,j,i,j,1);
if(mp[i][j-1]) bfs(i,j-1,i,j,2);
if(mp[i][j+1]) bfs(i,j+1,i,j,3);
}
}
//预处理,建图
while(q--){
int ex,ey,sx,sy,tx,ty;
scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
if(sx==tx&&sy==ty){ puts("0"); continue; } bfs(ex,ey,sx,sy,4); spfa(sx,sy); int ans=0x3f3f3f3f;
for(int i=0;i<4;i++) ans=min(ans,dist[tx*30*4+ty*4+i]);
(ans==0x3f3f3f3f)?puts("-1"):printf("%d\n",ans);
}
return 0;
}

[ NOIP2013 D2-T3 ] 华容道的更多相关文章

  1. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

  2. [NOIP2015]运输计划 D2 T3 LCA+二分答案+差分数组

    [NOIP2015]运输计划 D2 T3 Description 公元2044年,人类进入了宇宙纪元. L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有 ...

  3. [NOIP2013 提高组] 华容道 P1979 洛谷

    [NOIP2013 提高组] 华容道 P1979 洛谷 强烈推荐,更好的阅读体验 经典题目:spfa+bfs+转化 题目大意: 给出一个01网格图,和点坐标x,y空格坐标a,b,目标位置tx,ty要求 ...

  4. [NOIP2016]愤怒的小鸟 D2 T3

    Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的 ...

  5. NOIP2013 D1 T3 货车运输

    好吧,遇上这种题,作为蒟蒻的我第一个想到的就是怎么打暴力,然而暴力都打不好QAQ!!!于是只能等教练讲解以后,然后在大犇的指导下终于做出来了. 对了,,好像还,没上题....: 题目描述 A 国有 n ...

  6. 洛谷1967货车运输 即 NOIP2013 DAY1 T3

    题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...

  7. NOIP2013 DAY2 T3火车运输

    传送门 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况 ...

  8. 逛公园[NOIP2017 D2 T3](dp+spfa)

    题目描述 策策同学特别喜欢逛公园. 公园可以看成一张 \(N\)个点\(M\) 条边构成的有向图,且没有自环和重边.其中 1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值,代表策策经过这条 ...

  9. NOIP2012 D2 T3 疫情控制 洛谷P1084

    题目链接:https://www.luogu.org/problemnew/show/P1084 算法:倍增,二分答案,贪心 + 瞎搞.. 背景:上学长的数论课啥也听不懂,于是前去提高组找安慰.不巧碰 ...

  10. [NOIP2013提高组]华容道

    这道题第一眼看是暴力,然后发现直接暴力会TLE. 把问题转换一下:移动空格到处跑,如果空格跑到指定位置的棋子,交换位置. 这个可以设计一个状态:$[x1][y1][x2][y2]$,表示空格在$(x1 ...

随机推荐

  1. 通过HttpURLConnection下载图片到本地--批量下载

    一.背景说明 这篇文章讲述的是批量下载附件,在上一篇文章中,介绍了下载单个附件(上一篇文章). 二.实现思路 主要的实现思路:创建文件夹->文件夹中创建需要下载的文件->压缩文件夹-> ...

  2. [推荐]MyBatis 核心技术与面试 34 讲

    MyBatis 核心技术与面试 34 讲 职业生涯中常被问到: 如何成为某方面的高手? 如何快速搞定某项技术? 我现在的水平处于什么阶段? -- 我暗暗想,我们从小学到中学到大学,经历了大考三六九.小 ...

  3. 机器学习——K-Means算法

    1 基础知识 相似度或距离 假设有 $m$ 个样本,每个样本由 $n$ 个属性的特征向量组成,样本合集 可以用矩阵 $X$ 表示 $X=[x_{ij}]_{mn}=\begin{bmatrix}x_{ ...

  4. 3.15学习总结(Python爬取网站数据并存入数据库)

    在官网上下载了Python和PyCharm,并在网上简单的学习了爬虫的相关知识. 结对开发的第一阶段要求: 网上爬取最新疫情数据,并存入到MySql数据库中 在可视化显示数据详细信息 项目代码: im ...

  5. Python - 生成requirement.text 文件

    前言 该篇操作笔记摘自小菠萝 Python项目中,一般都会有一个 requirements.txt 文件 这个文件主要是用于记录当前项目下的所有依赖包及其精确的版本号,以方便在一个新环境下更快的进行部 ...

  6. [转载]ssh证书登录

    转载链接 前言 本文基于实际Linux管理工作,实例讲解工作中使用ssh证书登录的实际流程,讲解ssh证书登录的配置原理,基于配置原理,解决实际工作中,windows下使用SecureCRT证书登录的 ...

  7. [转载]CentOS 7安装配置Samba服务器

    假设我们有这样一个场景 共享名路径权限SHAREDOC/smb/docs所有人员包括来宾均可以访问RDDOCS/smb/tech仅允许特定组的用户进行读写访问 特定组的组名为RD,目前的Alice.J ...

  8. CF643F-Bears and Juice【组合数学】

    正题 题目链接:https://www.luogu.com.cn/problem/CF643F 题目大意 题目有点奇怪就直接放翻译了 有 \(n\) 只熊和若干桶果汁和恰好一桶酒,每一天每只熊会选择一 ...

  9. PHP审计之class_exists与任意实例化漏洞

    PHP审计之class_exists与任意实例化漏洞 前言 发现PHP的一些漏洞函数挺有意思,跟着七月火师傅的文章来学习. class_exists函数 函数说明 class_exists:(PHP ...

  10. 宝塔Linux面板搭建与安全狗安装(WEB服务器搭建与WAF安装)

    环境 系统:CentOS 7.3 (64位) 软件: 宝塔Linux 7.7 网站安全狗Linux-Apache版V2.3.18809(64位) 宝塔面板 下载和安装 网址:https://www.b ...