分析

这道题很容易想到令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)的更多相关文章

  1. NOIP2013 提高组day2 3 华容道 BFS

    描述 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间. 小 B 玩的华容道与经典的 ...

  2. 3537. 【NOIP2013提高组day2】华容道(搜索 + 剪枝)

    Problem 给出一个类似华容道的图.\(q\)次询问,每次给你起始点,终止点,空格位置,让你求最少步数 \(n,m\le 30, q\le 500\). Soultion 一道智障搜索题. 弱智想 ...

  3. NOIP2013 提高组 Day2

    期望得分:100+100+30+=230+ 实际得分:100+70+30=200 T2 觉得题目描述有歧义: 若存在2i却不存在2i+1,自己按不合法做的,实际是合法的 T3  bfs 难以估分 虽然 ...

  4. 积木大赛 noip2013提高组day2

    这道题一开始想到处理中间是0的位置,但这样时间太慢了,后来想到一种类似二分的方法,就是把这一段的最小值找到,全部减去最小值,然后有0一出现,就又递归处理前一段,每次答案就加上这一段的最小值: AC代码 ...

  5. NOIP2013 提高组day2 2 花匠 动规 找拐点 树状数组

    花匠 描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致. 具体 ...

  6. Noip2013 提高组 Day2 T1 积木大赛

    题目描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前,没有任何积木(可以看成 ...

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

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

  8. [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路

    [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路 题目大意: 对于长度为\(n(n\le10^5)\)的非负数列\(A\),每次可以选取一个区间\(-1\).问将数列清零至少需要 ...

  9. 18/9/16牛客网提高组Day2

    牛客网提高组Day2 T1 方差 第一眼看就知道要打暴力啊,然而并没有想到去化简式子... 可能因为昨晚没睡好,今天上午困死 导致暴力打了一个半小时,还不对... #include <algor ...

随机推荐

  1. node_modules .bin文件夹下的文件

    node_modues/.bin文件夹下,对于一个npm包,有两个可执行文件,没有后缀名的是是对应unix系的shell脚本,.cmd文件对应的是windows bat脚本,内容都是用node执行一个 ...

  2. PARAMETERS对象

    1. PARAMETERS的基本语法及定义 PARAMETERS可以参照数据字典字段或自定义数据类型创建文本输入域及单选框/复选框等, PARAMETERS只能创建一个单一的输入域且最多只能输入行,其 ...

  3. 19. Jmeter抓包之浏览器请求

    web测试过程中我们经常需要抓包,通常我们使用fiddler或者Charles.但是jmeter也可以抓包,而且非常好用,闲话不多说,下面进入正题.下面用一个例子进行说明 需求:bing首页搜索南京测 ...

  4. 浅谈JVM及原理

    前言 JVM一直是java知识里面进阶阶段的重要部分,如果希望在java领域研究的更深入,则JVM则是如论如何也避开不了的话题,本系列试图通过简洁易读的方式,讲解JVM必要的知识点. 运行流程 我们都 ...

  5. vue插槽用法(极客时间Vue视频笔记)

    vue插槽 插槽是用来传递复杂的内容,类似方法 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  6. Centos7 搭建pptp服务器

    1.检查是否支持pptp 返回ok即表示支持 modprobe ppp-compress-18 && echo ok 2.安装ppp yum install -y ppp 3.安装pp ...

  7. springboot 整合 tobato 的 fastdfs 实现文件上传和下载

    添加项目所需要的依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId ...

  8. CSP2019

    $CSP\space S$ 格雷码 $solution:$ 直接模拟即可. 时间复杂度 $O(n)$ . #include<iostream> #include<cstring> ...

  9. spring boot 枚举使用的坑3

    上一篇说到spring boot 使用jackson在枚举enum序列化和反序列化的问题, 再来说说在JPA中实体entity使用枚举的问题. 还是这个枚举: @Getter @AllArgsCons ...

  10. C# 静态方法调用非静态方法

    转载:http://blog.csdn.net/seattle1215/article/details/6657814 using System; using System.Collections.G ...