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. IIS托管Asp.net Core及Abp VNext

    默认方式安装IIS后,从官方网站下载IIS模块 https://dotnet.microsoft.com/download/dotnet-core/3.1 2个都需要安装 安装后,新建网站指向发布的磁 ...

  2. python库--pandas--Series.str--字符串处理

    原数据 import pandas as pd a = pd.Series(['aSd', 'asd', 'dfd fsAsf sfs']) b = pd.Series([None, 'asd', ' ...

  3. 轻量化模型系列--GhostNet:廉价操作生成更多特征

    ​  前言  由于内存和计算资源有限,在嵌入式设备上部署卷积神经网络 (CNN) 很困难.特征图中的冗余是那些成功的 CNN 的一个重要特征,但在神经架构设计中很少被研究. 论文提出了一种新颖的 Gh ...

  4. Object.keys( )与 for in 区别

    for in 一般用于对象的遍历: let obj = { a:1, b:2, } for(let key in obj){ console.log(key) } // a // b Object.k ...

  5. ARM架构安装ubuntu系统

    一.简介 arm开发板制作系统是比较麻烦,不论使用busybox还是yocto制作根文件系统对新手都比太友好,除非深度定制,否则使用ubuntu系统既可以满足,把更多的精力放在应用开发上. 二.准备材 ...

  6. File Inclusion(文件包含)

    File Inclusion,意思是文件包含(漏洞),是指当服务器开启allow_url_include选项时,就可以通过php的某些特性函数(include(),require()和include_ ...

  7. Django学习day15BBS项目开发4.0(完结)

    每日测验 """ 今日考题: 1.简述自定义标签,过滤器,inclusion_tag的方法,并简要说一说三者的特点及响应流程 2.简述个人侧边栏展示及筛选业务逻辑 3.简 ...

  8. mybatis一对一联表查询的两种常见方式

    1.一条语句执行查询(代码如下图)  注释:class表(c别名),teacher表(t别名)teacher_id为class表的字段t_id为teacher表的字段,因为两者有主键关联的原因,c_i ...

  9. 简单入门PHP中的多字节字符串操作

    什么是多字节的字符串操作呢?其实不少的同学可能都已经使用过了,但我们还是要从最基础的问题说起. 一个字符占几个字节并不是我们表面上看到的那样.正常情况下,一个数字或英文以及英文符号都是占用一个字节的. ...

  10. DEDE整合套件实现本地多个网站随意切换的开发环境

    一.修改WEB全局配置: 在Listen 80 后面添加自己的端口号. 例如,2020是我的端口 Listen 2020 二.修改WEB站点配置: a---在NameVirtualHost *:80后 ...