题目

此题目中存在三种棋盘的放置方法(空白,不能活动,能活动)。

而每次变化的格子一定在当前空白格子的周围,因此只需要对空白格子的周围四个状态考虑即可,因此我们设\(a[i][j][k]\)为白格子在(i,j)的k方向的一个状态,然后我们考虑,如果活动和不能活动的格子已经确定了,那么如果按照暴力的解法每次询问都需要对一开始的白格子向外扩展而得到的,这样会重复计算,因此我们可以快速计算出所有可移动的格子向周围移动所需要的时间,用\(dis[i][j][k][h]\)表示空格子在\((i,j)\)的\(k\)方向,然后\((i,j)\)跳到\((i+dx[h], j+dx[h])\)所需要的时间。这样就比较使状态表现的完全了,因为每次从一个格子移动到令一个格子时,就不需要用搜索来更新了,直接用此时间更新。

再向外扩展一下,则将状态抽象到图上的点,则原题就转化成了从起点到终点状态的最短路了。

对于每个询问,终点状态都有最多4个:

\(a[tx][ty][0/1/2/3]\)里面的任何满足条件且用时最短的的一个。

起点状态有4个,分别是\(a[sx][sy][0/1/2/3]\),但是此时白格子并没有到这四个方向上,因此我们用s表示一个不存在的节点,然后把这个节点跟起点的四个状态连边,边权分别是起始白格子位置到这四个方向的位置所用的时间。然后跑最短路就可以了

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int n, m, q, minn, ex, ey, sx, sy, tx, ty, cnt, tot, lin[1001001];
int dx[100] = {1, -1, 0, 0}, dy[100] = {0, 0, 1, -1};
int temp[1001][1001], vis[1001][1001], a[100][100][6];//a[i][j][0/1/2/3]分别表示(i,j)位置的空格子,方向为k时的状态编号
int dis[100][100][6][6];//空格子在(i,j)的k方向,然后i,j跳到(i+dx[h], j+dx[h])所需要的时间
struct dat {
int x, y, t;
};
struct edg {
int from, to, nex, len;
}e[1090100];
bool ch(int x, int y){if (x >= 1 && x <= n && y >= 1 && y <= m && temp[x][y]) return 1;return 0;}
inline void add(int f, int t, int l)
{
e[++cnt].to = t;
e[cnt].len = l;
e[cnt].from = f;
e[cnt].nex = lin[f];
lin[f] = cnt;
}
int bfs(int x, int y, int k, int h)//是白格子(x,y)到(k,h)的最小次数
{
queue <dat> q;
memset(vis, 0, sizeof(vis));
q.push({x, y, 0});
while ( !q.empty() )
{
dat now = q.front();
q.pop();
int wx = now.x, wy = now.y, wt = now.t;
if (wx == k && wy == h)
return wt;
for (int i = 0; i < 4; i++)
{
int nx = wx + dx[i], ny = wy + dy[i];
if (ch(nx, ny) && !vis[nx][ny])
q.push({nx, ny, wt + 1}), vis[nx][ny] = 1;
}
}
return inf;
}
inline void init()
{
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
scanf("%d", &temp[i][j]);
for (int k = 0; k < 4; k++)
a[i][j][k] = ++tot;//tot表示状态编号,(i,j)的k方向上必须可以放置白色方块。
}
memset(dis, 0x3f, sizeof(dis));//最短路初始赋为最大值。
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (temp[i][j])
{
temp[i][j] = 0;//先将该点设为不能走,防止跟空格交换
memset(vis, 0, sizeof(vis));
for (int k = 0; k < 4; k++)
for (int h = 0; h < 4; h++)
if ( ch(i + dx[h], j + dy[h]) && ch(i + dx[k], j + dy[k]) )
{
if (h == k)
dis[i][j][k][h] = 1;
else dis[i][j][k][h] = bfs(i + dx[k], j + dy[k], i + dx[h], j + dy[h]) + 1;//最后还要进行一次交换为了转移白色方块。
printf("%d %d %d %d\n", i, j, k, h);
}
temp[i][j] = 1;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
for (int k = 0; k < 4; k++)
for (int h = 0; h < 4; h++)
if (dis[i][j][k][h] < 1061109567)
add(a[i][j][k], a[i + dx[h]][j + dy[h]][h ^ 1], dis[i][j][k][h]);//异或是表示当前转移格子的反方向。
}
int dp[1001101], inq[10010011];
void spfa(int s)
{
// memset(inq, 0, sizeof(vis));
memset(dp, 0x3f, sizeof(dp));
queue <int> q;
dp[s] = 0;
q.push(s);
while (!q.empty())
{
int cur = q.front();
q.pop();
inq[cur] = 0;
for (int i = lin[cur]; i; i = e[i].nex)
{
int to = e[i].to;
if (dp[to] > dp[cur] + e[i].len)
{
dp[to] = dp[cur] + e[i].len;
if (!inq[to])
inq[to] = 1, q.push(to);
}
}
}
}
int main()
{
init();
for (int i = 1; i <= q; i++)
{
scanf("%d%d%d%d%d%d", &ex, &ey, &sx, &sy, &tx, &ty);
if (sx == tx && sy == ty)
{
printf("0\n");
continue;
}
int s = ++tot;
int t = ++tot;
temp[sx][sy] = 0;
for (int i = 0; i < 4; i++)
if (ch(sx + dx[i], sy + dy[i]))
{
int ha = bfs(sx + dx[i], sy + dy[i], ex, ey);
if (ha < inf)
add(s, a[sx][sy][i], ha);//首先将白格子移到当前起点的周围,此时初始化的状态就有用了
}
temp[sx][sy] = 1;
for (int i = 0; i < 4; i++)
if (ch(tx + dx[i], ty + dy[i]))
add(a[tx][ty][i], t, 0);//到达此状态则就已经到达了终点了,因为白格子在终点的周围, 所以终点此时不是白格子,而是棋子。
spfa(s);
if (dp[t] == inf)
printf("-1\n");
else
printf("%d\n", dp[t]);
}
return 0;
}

洛谷P1979华容道的更多相关文章

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

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

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

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

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

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

  4. 洛谷P1979 华容道

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

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

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

  6. 洛谷 P1979 [ NOIP 2013 ] 华容道 —— bfs + 最短路

    题目:https://www.luogu.org/problemnew/show/P1979 真是一道好题... 首先考虑暴力做法,应该是设 f[i][j][x][y] 记录指定棋子和空格的位置,然后 ...

  7. 洛谷 1979 华容道——最短路+dp

    题目:https://www.luogu.org/problemnew/show/P1979 感到无从下手.但不妨用dp的角度来看.因为空格只有在指定棋子的旁边才有用,所以状态记成制定棋子的位置与空格 ...

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

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

  9. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

随机推荐

  1. ajax 执行成功以后返回的数据走的是error方法而不是success方法的问题

    今天在一个功能的时候发现写的ajax的方法执行后台代码成功后返回前台时执行的是error方法而不是success方法,代码如下 jQuery('#form').ajaxSubmit({ type: & ...

  2. springMVC 任意文件读取相关路径

    在做检查的时候,发现一个路径是可以去读取文件的,但是平时的/etc/目录下都无法读取到,只能先读取web目录下的文件尝试. 因为知道是springMVC框架,所以可以先尝试该路径 ../../WEB- ...

  3. C#汉字转为Unicode编码

    主要用于生成json格式时,将汉字转成Unicoude编码,防止页面乱码. protected string GetUnicode(string text) { string result = &qu ...

  4. LATEX 数学公式基本语法

    作者:@houkai本文为作者原创,转载请注明出处:https://www.cnblogs.com/houkai/p/3399646.html TEX 是Donald E. Knuth 编写的一个以排 ...

  5. C# 查看系统进程

    //使用前需要引用 using System.Diagnostics; var processList = Process.GetProcesses().ToList();

  6. Springboot揭秘-快速构建微服务体系-王福强-2016年5月第一次印刷

    JavaConfig项目: spring IOC有一个非常核心的概念——Bean.由Spring容器来负责对Bean的实例化,装配和管理.XML是用来描述Bean最为流行的配置方式.Spring可以从 ...

  7. Kubemetes

    将应用docker化,配合ETCD.kubernetes等工具在容器的层面上实现高可用和负载均衡 容器化部署 容器化部署应用具有灵活.高效的使用资源,容器可以包含其所需的全部文件,如同在虚拟机上部署应 ...

  8. 【JVM学习笔记一】Java内存区域

    1. 运行时数据区域 1) 程序计数器 | 线程私有,存储线程运行时所执行字节码的行号,实现分支.循环.跳转.异常处理.线程恢复等基础功能 | Java方法,记录正在执行的虚拟机字节码指令的行号:Na ...

  9. excel 宏循环行数据 ,Excel统计所有sheet数据行数 VBA

    Sub fun1() '统计每一个sheet有多少行数据 Set s1 = Sheets("Sheet1") 'totalok = 0 To Sheets.Count s1.Cel ...

  10. Django:RestFramework之-------频率控制

    5.频率控制 5.1频率监控代码实现 import time VISIT_RECORD = {} class VisitThrottle(object): def __init__(self): #定 ...