[NOIP2013]华容道 题解(搜索)
[NOIP2013]华容道
【题目描述】




这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街。考后想想也是,数据这么小一定有他的道理。
首先由于是最小步数,所以BFS没跑了。那么我们大可把这道题分为两部分,首先先把白格子移到目标棋子附近,然后再把目标棋子移过去。第一步是很容易的,随便BFS一下就好了,关键是第二步。由于q不小,我们不可能每次询问都直接爆搜,但由于棋盘并不会发生本质改变,我们可以对一些东西进行预处理。
那每次询问时不变的是什么呢,我们求第二步时需要的又是什么呢?
首先我们可以明确的是一个棋子得以移动一定是它移动的目标上是空的,而我们只有一个空格子,所以一旦我们确定了空格子的位置整个棋盘的状态就明了了,所以我们要处理的是当白格子在哪个位置时我想把当前棋子移到上下左右某一位置所要花费的最少步数,那么我们真的需要开5维去表示这一状态吗?不必,四维就够了,对于白格子从之前道这个点附近其实本质和第一步无异,而在我们执行第二步时白格子在每次转移完一定是在目标棋子的上下左右位置,所以我们只需要处理出来目标棋子在当前格子时白格子在他上下左右时他向上下左右移动所耗费的步数即可。
然后,对于每一次询问,我们可以把每个点拆成四个,即白格子在这个点上下左右时的最小步数,慢慢搞即可。
对了,提醒一下,对于某个格子进行处理的时候一定不能通过该点进行更新。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<string>
#include<cmath>
using namespace std;
int n,m,q,a[][],zy[][],dis[][];
struct no{int x,y,k;};
bool check(int x,int y,int z){
if(x+zy[z][]!=&&x+zy[z][]!=n+&&y+zy[z][]!=&&y+zy[z][]!=m+&&a[x+zy[z][]][y+zy[z][]]) return ;
return ;
}
bool fw[][],f2[][];
int f[][][][];
void bfs1(int ax,int by){
memset(dis,0x3f,sizeof(dis));
memset(fw,,sizeof(fw));
queue<no> q1;
no aa;
aa.x=ax,aa.y=by;
dis[ax][by]=;
q1.push(aa);
fw[ax][by]=;
while(!q1.empty())
{
no t=q1.front();
q1.pop();
int x=t.x,y=t.y;
for(int i=;i<=;i++)
{
int xx=x+zy[i][],yy=y+zy[i][];
if(xx==||xx==n+||yy==||yy==m+) continue;
if(!a[xx][yy]) continue;
if(f2[xx][yy]) continue;
if(dis[xx][yy]>dis[x][y]+)
{
dis[xx][yy]=dis[x][y]+;
if(!fw[xx][yy])
{
fw[xx][yy]=;
no bb;
bb.x=xx,bb.y=yy;
q1.push(bb);
}
}
}
}
}
bool rd[][][];
int dis2[][][];
void spfa(int ax,int by){
memset(rd,,sizeof(rd));
no aa;
queue<no> q1;
aa.x=ax,aa.y=by;
if(check(ax,by,))
{
aa.k=;
q1.push(aa);
rd[ax][by][]=;
}
if(check(ax,by,))
{
aa.k=;
q1.push(aa);
rd[ax][by][]=;
}
if(check(ax,by,))
{
aa.k=;
q1.push(aa);
rd[ax][by][]=;
}
if(check(ax,by,))
{
aa.k=;
q1.push(aa);
rd[ax][by][]=;
}
while(!q1.empty())
{
no bb=q1.front();q1.pop();
int x=bb.x,y=bb.y,k=bb.k;
rd[x][y][k]=;
if(check(x,y,)&&dis2[x-][y][]>dis2[x][y][k]+f[x][y][][k]&&f[x][y][][k]!=-)
{
dis2[x-][y][]=dis2[x][y][k]+f[x][y][][k];
if(!rd[x-][y][])
{
rd[x-][y][]=;
no cc;
cc.x=x-,cc.y=y,cc.k=;
q1.push(cc);
}
}
if(check(x,y,)&&dis2[x+][y][]>dis2[x][y][k]+f[x][y][][k]&&f[x][y][][k]!=-)
{
dis2[x+][y][]=dis2[x][y][k]+f[x][y][][k];
if(!rd[x+][y][])
{
rd[x+][y][]=;
no cc;
cc.x=x+,cc.y=y,cc.k=;
q1.push(cc);
}
}
if(check(x,y,)&&dis2[x][y-][]>dis2[x][y][k]+f[x][y][][k]&&f[x][y][][k]!=-)
{
dis2[x][y-][]=dis2[x][y][k]+f[x][y][][k];
if(!rd[x][y-][])
{
rd[x][y-][]=;
no cc;
cc.x=x,cc.y=y-,cc.k=;
q1.push(cc);
}
}
if(check(x,y,)&&dis2[x][y+][]>dis2[x][y][k]+f[x][y][][k]&&f[x][y][][k]!=-)
{
dis2[x][y+][]=dis2[x][y][k]+f[x][y][][k];
if(!rd[x][y+][])
{
rd[x][y+][]=;
no cc;
cc.x=x,cc.y=y+,cc.k=;
q1.push(cc);
}
}
}
}
int main(){
memset(f,-,sizeof(f));
scanf("%d%d%d",&n,&m,&q);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&a[i][j]);
zy[][]=-,zy[][]=;
zy[][]=-,zy[][]=;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(!a[i][j]) continue;
f2[i][j]=;
for(int k=;k<=;k++)
{
if(check(i,j,k))
{
bfs1(i+zy[k][],j+zy[k][]);
for(int l=;l<=;l++)
{
if(check(i,j,l)&&dis[i+zy[l][]][j+zy[l][]]!=dis[][])
f[i][j][l][k]=dis[i+zy[l][]][j+zy[l][]]+;
}
}
}
f2[i][j]=;
}
} for(int i=;i<=q;i++)
{
int ex,ey,sx,sy,tx,ty;
scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
if(tx==sx&&ty==sy)
{
printf("0\n");
continue;
}
memset(dis2,0x3f,sizeof(dis2));
memset(f2,,sizeof(f2));
f2[sx][sy]=;
bfs1(ex,ey);
bool yx=;
for(int j=;j<=;j++)
{
if(check(sx,sy,j)&&dis[sx+zy[j][]][sy+zy[j][]]!=dis[][])
{
yx=;
dis2[sx][sy][j]=dis[sx+zy[j][]][sy+zy[j][]];
}
}
if(!yx)
{
printf("-1\n");
continue;
}
spfa(sx,sy);
int ans=0x7fffffff;
for(int j=;j<=;j++)
ans=min(ans,dis2[tx][ty][j]);
if(ans==0x7fffffff||ans==dis2[][][])
{
printf("-1\n");
continue;
}
else
printf("%d\n",ans);
}
return ;
}
[NOIP2013]华容道 题解(搜索)的更多相关文章
- [NOIP2013]华容道 题解
[NOIP2013]华容道 首先是一种比较显然的做法. 整个棋盘,除了起点,终点和空格,其他的方块是等价的. 对于终点,它始终不会变化,如果搜到终点结束搜索即可,所以我们不需要考虑终点. 所以需要考虑 ...
- Luogu 1979 NOIP 2013 华容道(搜索,最短路径)
Luogu 1979 NOIP 2013 华容道(搜索,最短路径) Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面 ...
- LOJ2613 NOIP2013 华容道 【最短路】*
LOJ2613 NOIP2013 华容道 LINK 这是个好题,具体题意比较麻烦可以直接看LINK中的链接 然后考虑我们可能的移动方式 首先我们需要把白块移动到需要移动块S的附近(附近四格) 然后我们 ...
- [CQOI2012]模拟工厂 题解(搜索+贪心)
[CQOI2012]模拟工厂 题解(搜索+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327574 链接题目地址:洛谷P3161 BZOJ P26 ...
- CF912E Prime Gift题解(搜索+二分答案)
CF912E Prime Gift题解(搜索+二分答案) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1314956 洛谷题目链接 $ $ CF题目 ...
- 3537. 【NOIP2013提高组day2】华容道(搜索 + 剪枝)
Problem 给出一个类似华容道的图.\(q\)次询问,每次给你起始点,终止点,空格位置,让你求最少步数 \(n,m\le 30, q\le 500\). Soultion 一道智障搜索题. 弱智想 ...
- 华容道 noip2013 70分搜索
题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 ...
- 华容道题解 NOIP2013 思路题!
第一次发紫题题解,居然在发布前太激动,把刚写好的还没发布的题解一个Ctrl+A和Backspace全删了.(所以这是二稿) luogu题目传送门 前置: 做本题一定要有的一些思想: 1.从简思想: 模 ...
- NOIP2013 DAY2题解
DAY2 T1积木大赛 传送门 题目大意:每次可以选区间[l,r]加1,最少选几次,让每个位置有 它应有的高度. 题解:O(n)扫一遍就好了.后一个比前一个的高度低,那么前一个已经把它覆盖了, 如果高 ...
随机推荐
- Android 查看APK文件的签名算法
查看APK使用了什么签名算法 keytool -list -printcert -jarfile xxx.apk 示例: 签名者 #1: 签名: 所有者: 发布者: 序列号: 有效期开始日期: 证书指 ...
- C++成员函数指针错误用法警示(成员函数指针与高性能的C++委托,三篇),附好多评论
今天做一个成绩管理系统的并发引擎,用Qt做的,仿照QtConcurrent搞了个模板基类.这里为了隐藏细节,隔离变化,把并发的东西全部包含在模板基类中.子类只需注册需要并发执行的入口函数即可在单独线程 ...
- android x86 7.0 32bit调试apk时出现的错误
detected problems with app native libraries libavcodec.so:text relocationslibavutil.solibswresample. ...
- 蚂蚁金服招聘-JAVA资深开发工程师/专家-蚂蚁金服保险
岗位描述: 1.协助业务方梳理业务需求,提供业务规划方案.架构设计方案: 2.负责业务系统的规划设计,制定产品的技术发展路线,完成重要业务模块及核心框架的搭建及编码实现: 3.发现和解决业务系统的技术 ...
- 给 Web 开发人员推荐的通用独立 UI 组件(二)
现代 Web 开发在将体验和功能做到极致的同时,对于美观的追求也越来越高.在推荐完图形库之后,再来推荐一些精品的独立 UI 组件.这些组件可组合在一起,形成美观而交互强大的 Web UI . 给 We ...
- IntelliJ IDEA Maven工程保证JDK版本不变
创建maven项目后修改pom文件idea会默认将jdk版本调回到1.5,这是因为没有在pom里面设置项目的jdk版本 解决方法: 在pom文件中设定jdk版本即可,以下这种写法会自动更新idea中的 ...
- 为什么使用剪切板时都用GlobalAlloc分配内存(历史遗留问题,其实没关系了)
我在使用剪切板时,发现通用的都是使用GlobalAlloc来分配内存,我就想不是说在Win32中GlobalAlloc和LocalAlloc是一样的那为什么不用LocalAlloc呢,原谅我的好奇心吧 ...
- VC++的Unicode编程
本文来自:http://tech.ddvip.com/2007-03/117395585321221.html 一.什么是Unicode 先从ASCII说起,ASCII是用来表示英文字符的一种编码规范 ...
- 15个非常棒的jQuery无限滚动插件【瀑布流效果】
现在,最热门的网站分页趋势之一是jQuery的无限滚动(也即瀑布流).如果你碰巧观察Pinterest的网站,如Facebook,Twitter和deviantART的,你会发现无限滚动的动作,当旧的 ...
- 利用POi3.8导出excel产生大量xml临时文件怎么办?
在实际项目中,经常会用到POI3.8来导出excel.而导出excel的时候,会因为残留大量以.xml结尾的文件而导致服务器存储空间急剧增长,最后导致系统挂了.为此,该怎么办呢? .xml后缀残留文件 ...