题目

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

而每次变化的格子一定在当前空白格子的周围,因此只需要对空白格子的周围四个状态考虑即可,因此我们设\(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. mybatis使用用stdout-logging日志显示sql语句

    在开发中,我们很多时候需要知道当前执行的sql语句是什么样的,但是默认mybatis是不显示sql的,此时我们就可以使用stdout-logging了.1.创建mybatis-config.xml文件 ...

  3. python基础03day

    # 1. # 创建字符串变量的三种写法及其区别 # 代码: #‘’.“”.“““””” # 区别: # 2. # 简述,计算机编程语言的分类及特点 # 1.机器 # 2.汇编 # 3.高级 # 3.1 ...

  4. 编写可维护的JavaScript-随笔(二)

    一.注释 1. 单行注释 a)      以两个斜线开始,以行位结束 b)      独占一行的注释,用来解释下一行的代码, c)      注释行之前总有一个空行 d)      缩进层级与下一行代 ...

  5. 8 smali文件格式

    Apktool反编译apk后程序中每一个类都会有一个smali文件. 一.当前类信息:smali文件的头三行描述了当前类的一些信息. Eg: .class <访问权限> [修饰关键字]&l ...

  6. 【转】如何把变量或者数组定义到SDRAM及任意位置

    我们开发软件的时候,经常会遇到到一个问题,就是内存不够,这个时候就纠结了,怎么办,有两种方法,第一种是扩展内存,外加SRAM或者SDRAM:第二种应该就是优化代码,也就是通常所说的把数组大小减一减,代 ...

  7. 【Iterm2】如何解决iterm2窗口自动隐藏的问题

    一.问题描述 当我们使用Iterm2的Hotkey Windom功能时,通过快捷键唤起Iterm2窗口后,然后鼠标在iterm2窗口之外触发点击操作就会让 iterm2窗口自动隐藏.. 这样有时候会觉 ...

  8. word 转pdf 再转图片--用在轻社群发文章

    #! /usr/bin/env python # -*- coding: utf-8 -*- import fitz import glob import os from win32com.clien ...

  9. SaltStack--配置管理

    saltstack配置管理 Saltstack状态模块 远程执行模块的执行是过程式,而状态是对minion的一种描述和定义,管理人员不需要关系部署任务如何完成的,只需要描述minion的状态描述.它的 ...

  10. SaltStack--使用salt-ssh

    SaltStack使用salt-ssh模式 salt-ssh 介绍 参考官档 salt-ssh是 0.17.0 新引入的一个功能,不需要minion对客户端进行管理,也可以不需要master:salt ...