【华容道】题解(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 ...
随机推荐
- 阶段3 1.Mybatis_06.使用Mybatis完成DAO层的开发_2 Mybatis中编写dao实现类的使用-保存操作
再完善.saveUser的方法 测试保存的操作 报错了 SqlSession的insert的源码 我们在执行Insert的时候,并没有把user对象传过去 usersex改成sex 再次测试
- C# 打印倒三角
void test6(int num) { try { #region 方法1 int maxstar = (num - 1) * 2 + 1; string line = ""; ...
- JS获取URL中参数值
一.正则法: function getQueryString(name) { var reg = new RegExp('(^|&)' + name + '=([^&]*)(& ...
- ES 集群管理(集群规划、集群搭建、集群管理)
一.集群规划 搭建一个集群我们需要考虑如下几个问题: 1. 我们需要多大规模的集群? 2. 集群中的节点角色如何分配? 3. 如何避免脑裂问题? 4. 索引应该设置多少个分片? 5. 分片应该设置几个 ...
- django连接数据库的类型
字段类型 django的models里面字段类型除了上面的常用的 models.CharField和models.IntegerField,还有更多的类型 1.models.AutoField 自增列 ...
- 【HANA系列】SAP HANA 2.0简介
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA 2.0简介 ...
- GCC 环境变量 & eclipse CDT 头文件配置
转:http://blog.csdn.net/statdm/article/details/7751000 GCC 环境变量 & eclipse CDT 头文件配置 在unix 下使用e ...
- 网络编程.iocp
1.(20191212)查到的一些资料:java从 JDK7开始 引入AOI(即 NIO2).然后 实现 IOCP使用的是 AsynchronousChannelGroup.AsynchronousS ...
- docker安装tomcat&部署javaweb程序
一.docker定制简单的java-web应用镜像 网址: 1.jdk下载网址:https://www.oracle.com/technetwork/java/javase/downloads/jdk ...
- JavaScript的二维数组
二维数组的初始化: 实例① var arr = [[1,2],['a','b']]; console.log(arr[1][0]); //a 第2列第1行所在的元素 实例② var arr = new ...