题意:$n*m$棋盘上$n*m-1$颗棋子,有且只有一个格子为空白格子,每个棋子大小$1*1$

   有些棋子可以移动,而有些棋子固定,任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。

   游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。

   现给定棋盘,q个询问,每次给出起始点,目标点,白块的位置,问最少步数,如果到不了输出-1

输入输出样例

输入样例#1:

3 4 2
0 1 1 1
0 1 1 0
0 1 0 0
3 2 1 2 2 2
1 2 2 2 3 2
输出样例#1:

2
-1

【输入输出样例说明】

棋盘上划叉的格子是固定的,红色格子是目标位置,圆圈表示棋子,其中绿色圆圈表示目标棋子。

  1. 第一次游戏,空白格子的初始位置是(3,2)(图中空白所示),游戏的目标是将初始位置在(1,2)上的棋子(图中绿色圆圈所代表的棋子)移动到目标位置(2,2)(图中红色的格子)上。

移动过程如下:

  1. 第二次游戏,空白格子的初始位置是(1,2)(图中空白所示),游戏的目标是将初始位置在(2,2)上的棋子(图中绿色圆圈所示)移动到目标位置 (3,2)上。

要将指定块移入目标位置,必须先将空白块移入目标位置,空白块要移动到目标位置,必然是从位置(2,2)上与当前图中目标位置上的棋子交换位置,之后能与空白块交换位置的只有当前图中目标位置上的那个棋子,因此目标棋子永远无法走到它的目标位置, 游戏无法完成。

看完题:果断-----爆搜啊

      20分。。。。。。TLE  QAQ(不过貌似可以70分)

正解:

  脑补一下起始棋子移动的画面,起始棋子向终点移动一步,当且仅当空白格子与它相邻且在目标方向上

  所以,我们设dis[i][j][k][l][m]表示以i,j为起点,不经过与i,j相邻的m方向上的那个棋子,到各个点的最短路,

  考虑一下,白块与起始块交换后,起始块移动了一步,然后白块在起始块原来的位置上,

  要想让起始块再向目标前进一步,白块必须在与它相邻且在它目标方向的位置上,再与它交换才行,

  而dis数组恰好做到了这一点,找到白块不经过起始块到达起始块目标方向的块的最短路,直接统计,

  那一段有居多分支的搜索,我们直接省去了,节省了大量时间

  于是,相当于白块带着起始块满图瞎jb乱跑,跑到终点就行了QAQ

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cctype>
#include<queue>
#include<algorithm>
using namespace std;
#define int long long
#define olinr return
#define _ 0
#define love_nmr 0
#define DB double
int rx[]={,,,,-}; //四个方向
int ry[]={,,-,,};
int dis[][][][][]; //dis[i][j][k][l][m]代表从(i,j)到(k,l)不经过(i,j)m边的那一个格子的最短路(m=上,下,左,右)
bool mp[][]; //地图
bool viss[][]; //spfa的vis
bool cop[][]; //复制地图
int n;
int m;
int q;
int a,b,c,d,e,f; //空白格子x,y 起始点x,y 终点x,y
int ans; //答案
struct node
{
int x;
int y;
int dis;
};
struct wmy
{
int dir;
int x;
int y;
int dis;
}lv[];
queue<node> que;
int cnt;
inline int read()
{
int x=,f=;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
f=-f;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}
return x*f;
}
inline void put(int x)
{
if(x<)
{
x=-x;
putchar('-');
}
if(x>)
put(x/);
putchar(x%+'');
}
inline void spfa(int x,int y,int k)
{
while(!que.empty()) que.pop();
dis[x][y][x][y][k]=;
que.push((node){x,y,});
while(!que.empty())
{
node tp=que.front();
que.pop();
viss[tp.x][tp.y]=false;
for(int i=;i<=;i++)
{
int xx=tp.x+rx[i];
int yy=tp.y+ry[i];
if(xx>=&&xx<=n&&yy>=&&yy<=m&&mp[xx][yy]&&dis[x][y][xx][yy][k]>dis[x][y][tp.x][tp.y][k]+)
{
dis[x][y][xx][yy][k]=dis[x][y][tp.x][tp.y][k]+;
if(!viss[xx][yy])
{
viss[xx][yy]=true;
que.push((node){xx,yy,});
}
}
}
}
}
inline void bfs()
{
while(!que.empty()) que.pop();
que.push((node){a,b,});
cop[a][b]=;
while(!que.empty())
{
node tp=que.front();
que.pop();
for(int i=;i<=;i++)
{
int xx=tp.x+rx[i];
int yy=tp.y+ry[i];
if(xx>=&&xx<=n&&yy>=&&yy<=m&&cop[xx][yy])
{
if(xx==c&&yy==d)
{
cnt++; //记录白块到起始块的信息
lv[cnt].x=tp.x;
lv[cnt].y=tp.y;
lv[cnt].dis=tp.dis;
lv[cnt].dir=i;
}
else
{
cop[xx][yy]=;
que.push((node){xx,yy,tp.dis+});
}
}
}
}
}
inline void dfs(int x,int y,int lst1,int lst2,int dir,int tot)
{
if(tot>=ans) return;
if(x==e&&y==f) //找到终点
{
ans=tot;
return;
}
mp[x][y]=; //记为起始块已走过
for(int i=;i<=;i++)
{
int xx=x+rx[i];
int yy=y+ry[i];
if(xx>=&&xx<=n&&yy>=&&yy<=m&&mp[xx][yy]&&dis[lst1][lst2][xx][yy][dir]<=1e5)
dfs(xx,yy,x,y,i,tot+dis[lst1][lst2][xx][yy][dir]+); //起始块向目标方向移动距离=白块从原来到现在的距离+1
}
mp[x][y]=; //回溯 }
signed main()
{
n=read();
m=read();
q=read();
memset(dis,,sizeof dis); //五位数组,赋值1已经很大了
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
mp[i][j]=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(mp[i][j])
for(int k=;k<=;k++) //跑spfa,处理不经过m方向的点的最短路(方法:把那个点变成无法走)
{
int xx=i+rx[k];
int yy=j+ry[k];
if(xx>=&&xx<=n&&yy>=&&yy<=m&&mp[xx][yy])
{
mp[xx][yy]=;
spfa(i,j,k);
mp[xx][yy]=;
}
}
while(q--)
{
cnt=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
cop[i][j]=mp[i][j]; //复制一遍进行操作
a=read();
b=read();
c=read();
d=read();
e=read();
f=read();
if(c==e&&d==f) //起点=终点
{
put();
putchar('\n');
continue;
}
bfs(); //找到初始时空白块到起始块的距离
if(!cnt) //空白块连起始块都到不了QAQ
{
put(-);
putchar('\n');
continue;
}
ans=0x7ffffffff; //步数初始极大值
for(int i=;i<=cnt;i++)
dfs(c,d,lv[i].x,lv[i].y,lv[i].dir,lv[i].dis); //模拟跑路过程
put(ans==0x7ffffffff? -:ans);
putchar('\n');
}
olinr ~~(^_^)+love_nmr;
}
 

P1979 华容道的更多相关文章

  1. 洛谷 P1979 华容道 解题报告

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

  2. 洛谷P1979 华容道(70分 暴力)

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

  3. Luogu P1979 华容道(bfs+最短路)

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

  4. P1979华容道(神仙题)

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

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

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

  6. P1979 华容道 spfa题解

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

  7. luogu P1979 华容道

    solution 被假hash可了半天....sadQAQ code // luogu-judger-enable-o2 #include<queue> #include<cstdi ...

  8. 洛谷P1979 华容道

    神の契约 题目大意:自己看去... 题解:做了一下午...本蒟蒻立志要写全网最详细的题解.╭(╯^╰)╮ begin.... 暴力70分.可以让空格子到处乱走,只要某个状态的指定格子到目标格子,那么此 ...

  9. bzoj P1979 华容道【bfs+spfa】

    调死我了-- 首先观察移动方式,需要移动的格子每次移动到相邻格子,一定是先把空白格子挪过去,所以我们得到一种做法,就是bfs预处理出每一个格子的四联通格子之间的空白格子移动距离建边,注意这个移动是不能 ...

随机推荐

  1. Mysql教程:[1]下载安装配置详细教程

    如果不小心你下载了免安装的mysql,那么你比较倒霉,你找不到setup文件,还得自己去配置很多东西,然后再使用命令安装.所以我今天呢写一篇教程,写的尽量详细,即便是菜鸟也能安装,我自己安装过很多遍了 ...

  2. react核心知识点高度总结

    本文系统的将react的语法以最简练的方式列举出来 安装 写在前面 JSX 组件的定义 state 生命周期 方法 条件渲染 列表 表单 组合嵌套 扩展语法 context传递props 错误拦截 r ...

  3. 第五章 Java中锁

    Lock接口 锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源(但是有些锁可以允许多个线程并发的访问共享资源,比如读写锁).在Lock接口出现之前,Java程序 ...

  4. apache + tomcat 负载均衡分布式集群配置

    Tomcat集群配置学习篇-----分布式应用 现目前基于javaWeb开发的应用系统已经比比皆是,尤其是电子商务网站,要想网站发展壮大,那么必然就得能够承受住庞大的网站访问量:大家知道如果服务器访问 ...

  5. tomcat是一个应用服务器

    总的来说,tomcat的身份可以看作一个WEB容器,但实际上是一个应用程序服务器.为什么这么说?1.因为你从tomcat内部看你会发现其实tomcat内置了一个轻量级的WEB服务器,用于转发html文 ...

  6. HDU 4912 LCA + 贪心

    题意及思路 说一下为什么按LCA深度从深到浅贪心是对的.我们可以直观感受一下,一条的路径会影响以这个lca为根的这颗树中的链,而深度越深,影响范围越小,所以先选影响范围小的路径. #include & ...

  7. 大话设计模式--Python

    作者:五岳 出处:http://www.cnblogs.com/wuyuegb2312 上一周把<大话设计模式>看完了,对面向对象技术有了新的理解,对于一个在C下写代码比较多.偶尔会用到一 ...

  8. Condition实现多个生产者多个消费者

    Condition实现多对多交替打印: import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.R ...

  9. 在Mac OS里安装和升级Git

    在此记录,给自己看,也给别人参考. 进入终端,查看当前Git版本,输入指令:git --version 输入which git回车,可以查看当前git在什么位置 经查,版本:2.10.0,版本较低,为 ...

  10. JavaPersistenceWithMyBatis3笔记-第3章SQL Mappers Using XMLs-001

    一. 1.Mapper 2.Service 3.Domain package com.mybatis3.domain; import java.io.Serializable; import java ...