http://codevs.cn/problem/3290/

据说2013年的noip非常难,但Purpleslz学长还是AK了。能A掉这道题真心orz。

设状态$(i,j,k)$表示目标棋子在$(i,j)$这个位置,空格在紧贴着目标棋子的$k$方向,$0≤k<4$。

因为目标棋子要移动,空格肯定在它旁边。往空格的方向走一步,空格便出现在它另一边。对于这两个状态连边,边权为1。

为了使目标棋子向某一方向移动,需要目标棋子不动,空格从紧贴着目标棋子的某一方向移动到紧贴着目标棋子的另一个方向。对于固定目标棋子位置但空格对于目标棋子的方向不同的状态之间互相连边,边权需要bfs求得。

对于每个询问,给出初始空格的位置,bfs出初始的空格移动到目标棋子旁边四个位置的最短距离,并连边, 边权为最短距离。

最后跑spfa求出到达目标棋子到达终点需要走的最短路。

时间复杂度$O(nm)$,因为边数是nmk级别的,而且k是个常数,所以把k忽略掉233 _(:з」∠)_k都快比nm大了QwQ

话说spfa的复杂度真的是$O(E)$的吗(/"≡ _ ≡)/~┴┴

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 33;
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, 1, 0, -1};
int in() {
int k = 0, fh = 1; char c = getchar();
for(; c < '0' || c > '9'; c = getchar())
if (c == '-') fh = -1;
for(; c >= '0' && c <= '9'; c = getchar())
k = (k << 3) + (k << 1) + c - '0';
return k * fh;
} struct node {int nxt, to, w;} E[20003];
int Move[33][33][4][4], point[4003], cnt = 0, a[33][33], n, m, qq;
int number[33][33][4], tot = 0; void ins(int u, int v, int w) {E[++cnt] = (node) {point[u], v, w}; point[u] = cnt;} bool can(int x, int y) {
return ((x >= 1) && (x <= n) && (y >= 1) && (y <= m) && (a[x][y] == 1));
} struct Point {
int x, y, d;
Point(int _x = 0, int _y = 0, int _d = 0) : x(_x), y(_y), d(_d) {}
bool operator == (const Point &A) const {
return x == A.x && y == A.y;
}
} q[1003]; int cross(int x, int y, int h, int hh) {
Point s, t;
s = Point(x + dx[h], y + dy[h], 0);
t = Point(x + dx[hh], y + dy[hh], 0);
a[x][y] = 0;
int head = 0, tail = 1;
q[1] = s; a[s.x][s.y] = 1; Point u, v;
while (head != tail) {
u = q[++head];
if (u == t) break;
for(int d = 0; d < 4; ++d)
if (can(u.x + dx[d], u.y + dy[d])) {
v = Point(u.x + dx[d], u.y + dy[d], u.d + 1);
q[++tail] = v;
a[v.x][v.y] = 0;
}
} for(int i = 1; i <= tail; ++i)
a[q[i].x][q[i].y] = 1; a[x][y] = 1;
if (u == t) return u.d;
else return 0x7fffffff;
} void dealwith(int x, int y) {
int ed;
for(int d = 0; d < 4; ++d)
if (can(x + dx[d], y + dy[d]))
for(int dd = d + 1; dd < 4; ++dd)
if (can(x + dx[dd], y + dy[dd])) {
ed = Move[x][y][d][dd] = Move[x][y][dd][d] = cross(x, y, d, dd);
if (ed != 0x7fffffff) {
ins(number[x][y][d], number[x][y][dd], ed);
ins(number[x][y][dd], number[x][y][d], ed);
}
}
} int dis(Point g, Point s, Point t) {
int head = 0, tail = 1;
s.d = 0; q[1] = s; a[s.x][s.y] = 0; a[g.x][g.y] = 0;
Point u, v;
while (head != tail) {
u = q[++head];
if (u == t) break;
for(int d = 0; d < 4; ++d)
if (can(u.x + dx[d], u.y + dy[d])) {
v = Point(u.x + dx[d], u.y + dy[d], u.d + 1);
q[++tail] = v;
a[v.x][v.y] = 0;
}
} a[g.x][g.y] = 1;
for(int i = 1; i <= tail; ++i)
a[q[i].x][q[i].y] = 1;
if (u == t) return u.d;
else return 0x7fffffff;
} queue <int> Q;
int dist[4003], inq[4003]; void spfa(int s) {
memset(dist, 127, sizeof(int) * (tot + 1));
Q.push(s); dist[s] = 0; inq[s] = true;
int u;
while (!Q.empty()) {
u = Q.front(); Q.pop(); inq[u] = false;
for(int i = point[u]; i; i = E[i].nxt)
if (dist[u] + E[i].w < dist[E[i].to]) {
dist[E[i].to] = dist[u] + E[i].w;
if (!inq[E[i].to]) {
Q.push(E[i].to);
inq[E[i].to] = true;
}
}
}
} int main() {
n = in(); m = in(); qq = in();
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
a[i][j] = in(); for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if (a[i][j] == 1)
for(int d = 0; d < 4; ++d)
if (can(i + dx[d], j + dy[d]))
number[i][j][d] = ++tot; for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if (a[i][j] == 1) dealwith(i, j); for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if (a[i][j] == 1)
for(int d = 0; d < 4; ++d)
if (can(i + dx[d], j + dy[d]))
ins(number[i][j][d], number[i + dx[d]][j + dy[d]][(d + 2) % 4], 1); ++tot;
Point e, s, t;
int now = cnt, ans;
while (qq--) {
e.x = in(); e.y = in(); s.x = in(); s.y = in(); t.x = in(); t.y = in();
if (s == t) {puts("0"); continue;}
cnt = now; point[tot] = 0;
for(int d = 0; d < 4; ++d)
if (can(s.x + dx[d], s.y + dy[d]))
ins(tot, number[s.x][s.y][d], dis(s, e, Point(s.x + dx[d], s.y + dy[d], 0)));
spfa(tot);
ans = 0x7fffffff;
for(int d = 0; d < 4; ++d)
ans = min(ans, dist[number[t.x][t.y][d]]);
printf("%d\n", ans == 2139062143 ? -1 : ans);
} return 0;
}

终于A掉了。注意特判起点和终点相同

【CodeVS 3290】【NOIP 2013】华容道的更多相关文章

  1. Luogu 1979 NOIP 2013 华容道(搜索,最短路径)

    Luogu 1979 NOIP 2013 华容道(搜索,最短路径) Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面 ...

  2. noip 2013 华容道

    /*双向bfs (得分和单项的一样多....)70*/ #include<iostream> #include<cstdio> #include<cstring> ...

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

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

  4. codevs 3290 华容道(SPFA+bfs)

    codevs 3290华容道 3290 华容道 2013年NOIP全国联赛提高组 时间限制: 1 s  空间限制: 128000 KB 题目描述 Description 小 B 最近迷上了华容道,可是 ...

  5. NOIP 2013 货车运输【Kruskal + 树链剖分 + 线段树 】【倍增】

    NOIP 2013 货车运输[树链剖分] 树链剖分 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在 ...

  6. [Noip 2013 Day1-3] 货车运输 做法总结

    [Noip 2013 Day1-3] 货车运输 做法总结 Online Judge:Luogu-1967 Label:启发式合并,离线,整体二分,按秩合并,倍增,最大生成树 打模拟离线赛时做到,顺便总 ...

  7. Codevs 3289 花匠 2013年NOIP全国联赛提高组

    3289 花匠 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 花匠栋栋种了一排花,每株花都 ...

  8. 【NOIP 2013 DAY2 T3】 华容道(spfa)

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

  9. 【CodeVS 3289】【NOIP 2013】花匠

    http://codevs.cn/problem/3289/ dp转移,树状数组维护前缀max和后缀max进行优化,$O(nlogn)$. #include<cstdio> #includ ...

随机推荐

  1. 怎么实现ZBrush中Alt键和Shift键的灵活运用

    ZBrush是一个数字雕刻和绘画软件,它以强大的功能和直观的工作流程彻底改变了整个三维雕刻行业.在一个简洁的界面中,ZBrush为当代数字艺术家提供了世界上最先进的工具.利用快捷键能使操作更快捷高效, ...

  2. 最新discuz模版制作7堂课让你精通discuz模版制作

    第一课  基本知识储备一.基本 HTML 代码二.网站语言编码  三.DIV+CSS 认知及应用 第二课  必备软件.环境配置及程序安装 第三课  DISCUZ 构架详解 一.DISCUZ 基础构架讲 ...

  3. KSFramework常见问题:Lua脚本热重载,内存状态数据丢失?

    Lua热重载 内存数据在重载后会丢失 KSFramework中,所有的UI Lua脚本是可以重载的.脚本中的一些内存数据,在重载后会丢失,比如: -- 记录一个UI界面被打开了多少次 function ...

  4. HTML5 WebSocket 技术介绍

    WebSocket是html5规范新引入的功能,用于解决浏览器与后台服务器双向通讯的问题,使用WebSocket技术,后台可以随时向前端推送消息,以保证前后台状态统一,在传统的无状态HTTP协议中,这 ...

  5. SQL部分 数据库的建立 增删改查

    数据库: 结构化查询语言(Structured Query Language)简称SQL: 数据库管理系统(Database Management System)简称DBMS: 数据库管理员(Data ...

  6. [No000055]教你早晨清肠、除口臭、色斑、大肚腩

    [长生不老的秘诀] 释.道.医三家有个共同的秘诀:"要叫人不死. 肠中须无屎". 佛家除要求人们戒杀吃素外,还认为早饭是天食,中饭是人食,晚饭是鬼食. 因此,为了身体健康,不妨碍修 ...

  7. bzoj1067 降雨量&&vijos1265 暴风雨

    描述 话说这日,李逍遥与阿奴正欲前往桃花源拿寿葫芦,突然电闪雷鸣,天降暴雨,弄得两人措手不及,只得到附近的树洞避雨. "哎,大理不是本应旱灾的吗?怎么会突降暴雨呢?"李逍遥嘀咕道. ...

  8. 运用.net core配合VS 2015制作nuget包

    from:http://www.cnblogs.com/zeusro/p/5171084.html 运用.net core配合VS 2015制作nuget包 以往做nuget包我们一般要么用命令行,要 ...

  9. Regression analysis

    Source: http://wenku.baidu.com/link?url=9KrZhWmkIDHrqNHiXCGfkJVQWGFKOzaeiB7SslSdW_JnXCkVHsHsXJyvGbDv ...

  10. ios开发--多台电脑共用一个开发证书的方法

    Xcode5 以前的操作步骤是: idp证书如何给另一台机子使用 先在原电脑上用Xcode->Windows->Organizer, 再点击Developer profile, 在其最下面 ...