【华容道】题解(NOIP2013提高组day2)
分析
这道题很容易想到令f[x][y][x1][y1]表示空白块在(x,y)、指定棋子在(x1,y1)时的最少步数,让空白块和四周的棋子交换,当空白块要和指定棋子交换时,把指定棋子移动,搞一下BFS就可以了,时间复杂度O(qn2m2),可以拿60+。
因为只有空白块在指定棋子的旁边,指定棋子才能移动,而且指定棋子每次移动后,空白块仍然与指定棋子相邻。所以令move[x][y][k][l]表示指定棋子在(x,y),空白块在与指定棋子相邻的k方向,要将空白块移动到与指定棋子相邻的l方向需要的步数。那么首先把move预处理出来,在每一次讯问中,把空白格移到指定棋子相邻的存在的格子,做一次spfa,就可以了。
spfa:令f[x][y][k]表示指定棋子在(x,y),空白块在与指定棋子相邻的k方向的状态需要的最少步数。转移显然,(xx,yy)是要移动到的方向,i表示指定格子要向i方向走,k1指移动后空白块在与指定棋子相邻的k方向,k1即是i的相反方向,那么f[x][y][k]+move[x][y][k][i]+1==>f[xx][yy][k1]。
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
using namespace std;
int n,m,qu,a[40][40]={0},z[4][2]={{0,1},{1,0},{0,-1},{-1,0}},d[1000000][5],move[31][31][5][5],f[31][31][5];
int d1[1000000][5],xx,yy;
bool bz[31][31],b[31][31][5];
int bfs(int x,int y,int k1,int k2)
{
int i,j,k,l,head=0,tail=1,x1=z[k1][0]+x,y1=z[k1][1]+y,x2=z[k2][0]+x,y2=z[k2][1]+y;
int xx,yy;
if(!a[x1][y1] || !a[x2][y2]) return 0;
memset(bz,true,sizeof(bz));
bz[x][y]=false;
d[1][0]=0;
d[1][1]=x1;
d[1][2]=y1;
bz[x1][y1]=false;
while(head<tail)
{
k=++head;
for(i=0;i<=3;i++)
{
xx=d[k][1]+z[i][0];
yy=d[k][2]+z[i][1];
if(bz[xx][yy] && a[xx][yy])
{
d[++tail][0]=d[k][0]+1;
d[tail][1]=xx;
d[tail][2]=yy;
bz[xx][yy]=false;
if(xx==x2 && yy==y2)
{
move[x][y][k1][k2]=d[tail][0];
return 0;
}
}
}
}
return 0;
}
int bk(int x,int y,int x1,int y1)
{
memset(bz,true,sizeof(bz));
d1[0][0]=0;
bz[x][y]=false;
bz[x1][y1]=false;
d[1][0]=0;
d[1][1]=x;
d[1][2]=y;
int head=0,tail=1,i,j,k;
while(head<tail)
{
k=++head;
for(i=0;i<=3;i++)
{
xx=d[k][1]+z[i][0];
yy=d[k][2]+z[i][1];
if(bz[xx][yy] && a[xx][yy])
{
d[++tail][0]=d[k][0]+1;
d[tail][1]=xx;
d[tail][2]=yy;
bz[xx][yy]=false;
}
else
if(xx==x1 && yy==y1)
{
d1[++d1[0][0]][0]=d[k][0];
d1[d1[0][0]][1]=xx;
d1[d1[0][0]][2]=yy;
d1[d1[0][0]][3]=(i+2)%4;
}
}
}
}
int pre()
{
memset(move,43,sizeof(move));
int i,j,k,l;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(a[i][j])
for(k=0;k<=3;k++)
for(l=0;l<=3;l++)
{
if(k==l)
{
move[i][j][k][l]=0;
}
else bfs(i,j,k,l);
}
return 0;
}
int spfa()
{
int i,j,k,l,head=0,tail=d1[0][0];
memset(b,true,sizeof(b));
for(i=1;i<=d1[0][0];i++)
{
f[d1[i][1]][d1[i][2]][d1[i][3]]=d1[i][0];
b[d1[i][1]][d1[i][2]][d1[i][3]]=false;
}
while(head<tail)
{
k=++head;
b[d1[k][1]][d1[k][2]][d1[k][3]]=true;
for(i=0;i<=3;i++)
{
xx=d1[k][1]+z[i][0];
yy=d1[k][2]+z[i][1];
if(f[d1[k][1]][d1[k][2]][d1[k][3]]+move[d1[k][1]][d1[k][2]][d1[k][3]][i]+1<f[xx][yy][(i+2)%4])
{
f[xx][yy][(i+2)%4]=f[d1[k][1]][d1[k][2]][d1[k][3]]+move[d1[k][1]][d1[k][2]][d1[k][3]][i]+1;
if(b[xx][yy][(i+2)%4])
{
b[xx][yy][(i+2)%4]=false;
d1[++tail][1]=xx;
d1[tail][2]=yy;
d1[tail][3]=(i+2)%4;
}
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&qu);
int i,j,k,l;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&a[i][j]);
int p=-1;
pre();
while(qu--)
{
int x,y,x1,y1,x2,y2,head=0,tail=1,xx,yy;
scanf("%d%d%d%d%d%d",&x,&y,&x1,&y1,&x2,&y2);
bk(x,y,x1,y1);
if(x2==x1 && y2==y1)
{
printf("0\n");
}
else
{
memset(f,43,sizeof(f));
int ans=f[0][0][0];
spfa();
for(i=0;i<=3;i++)
ans=min(ans,f[x2][y2][i]);
if(ans==f[0][0][0]) printf("-1\n");
else printf("%d\n",ans);
}
}
}
【华容道】题解(NOIP2013提高组day2)的更多相关文章
- NOIP2013 提高组day2 3 华容道 BFS
描述 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间. 小 B 玩的华容道与经典的 ...
- 3537. 【NOIP2013提高组day2】华容道(搜索 + 剪枝)
Problem 给出一个类似华容道的图.\(q\)次询问,每次给你起始点,终止点,空格位置,让你求最少步数 \(n,m\le 30, q\le 500\). Soultion 一道智障搜索题. 弱智想 ...
- NOIP2013 提高组 Day2
期望得分:100+100+30+=230+ 实际得分:100+70+30=200 T2 觉得题目描述有歧义: 若存在2i却不存在2i+1,自己按不合法做的,实际是合法的 T3 bfs 难以估分 虽然 ...
- 积木大赛 noip2013提高组day2
这道题一开始想到处理中间是0的位置,但这样时间太慢了,后来想到一种类似二分的方法,就是把这一段的最小值找到,全部减去最小值,然后有0一出现,就又递归处理前一段,每次答案就加上这一段的最小值: AC代码 ...
- NOIP2013 提高组day2 2 花匠 动规 找拐点 树状数组
花匠 描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致. 具体 ...
- Noip2013 提高组 Day2 T1 积木大赛
题目描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前,没有任何积木(可以看成 ...
- [NOIP2013 提高组] 华容道 P1979 洛谷
[NOIP2013 提高组] 华容道 P1979 洛谷 强烈推荐,更好的阅读体验 经典题目:spfa+bfs+转化 题目大意: 给出一个01网格图,和点坐标x,y空格坐标a,b,目标位置tx,ty要求 ...
- [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路
[NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路 题目大意: 对于长度为\(n(n\le10^5)\)的非负数列\(A\),每次可以选取一个区间\(-1\).问将数列清零至少需要 ...
- 18/9/16牛客网提高组Day2
牛客网提高组Day2 T1 方差 第一眼看就知道要打暴力啊,然而并没有想到去化简式子... 可能因为昨晚没睡好,今天上午困死 导致暴力打了一个半小时,还不对... #include <algor ...
随机推荐
- 测开之路一百五十四:ajax+json前后台数据交互
在实际工作中,前后端数据交互大部分都是用的json格式,后端把数据处理完后,把json传给前端,前端再解析 项目结构 models里面加入把数据转为字典的方法 from datetime import ...
- DELPHI中函数、过程变量的声明与应用
Procedure型变量: 在DELPHI中,函数.过程的地址可以赋给一个特殊类型的变量,变量可用如下方式声明: var p : procedure(num:integer); //过程 或: var ...
- Delphi回车键切换焦点
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- mysql中关于 like ,not like 的用法时不能显示空值的数据(空值不参与判断,直接过滤空值)
一般在项目中用法是(这种没办法显示空值的数据): select * from 表 where 字段 like %aaa%; 解决空值不显示(除了显示的数据外,空值数据也可以显示): select * ...
- IP子网的划分
一.划分子网的具体步骤 已知192.168.1.0/24,划分8个子网(一个ip划分8个子网,即网络位不再是24位)1100 0000.1010 1000.0000 0001.0000 00001 . ...
- 安装Git并关联
下载git 打开git bash 生成key将 key绑定到帐号 输入命令 ssh-keygen -t rsa -C 'LoginName' 根据命令生成的地址找到对应文件复制密钥 打开github登 ...
- 只需要2个工具,百度云盘大文件就能用迅雷和IDM下载
不会代码,不懂脚本,没关系 ,能找到一座通往它们的桥梁,照样能到达彼岸. 这里以360极速浏览器为例. 在浏览器地址框输入以下地址直接到达浏览器安装扩展插件的地方(偷个懒,复制网址吧),https:/ ...
- Scrapy输出文件格式问题汇总
Q:Scrapy抓取的内容(包含中文)输出到JSON Lines文件时如何确保输出的是字符本身而不是其unicode编码? A:默认的JsonLinesItemExporter其ensure_asci ...
- [转帖]mysql.sock的作用
mysql.sock的作用 链接:http://blog.itpub.net/28602568/viewspace-1797619/ 标题:mysql.sock的作用 作者:lōττéry©版权所有[ ...
- 安装Pycharm(方便编辑代码的IDE(编辑器))以及 使用Pycharm新建项目
安装Pycharm(方便编辑代码的IDE(编辑器))以及 使用Pycharm新建项目 一.下载安装Pycharm 首先要下载Pycharm这个软件,官网的下载地址是: http://www.jetbr ...