Codeforces Gym101518E:The Pharaoh's Curse(BFS + 离散化)
题意
给出一个n*m的地图,人的当前位置是'S',还有不超过两个的箱子'X',任意多个按钮'B',不超过100个可以走的点'.',还有一个在边界的出口'E',当且仅当所有的按钮都被箱子盖住的时候,出口才会打开,人才可以走到出口,问最少需要的步数是多少。
思路
首先确定是搜索,那么状态表示的话,因为只有两个箱子,所以只要考虑人的位置和两个箱子各自的位置,但是n,m<=50,因此对于一个状态,要用50^6的数组去表示,很明显会爆空间。
考虑到只有不超过100个可以走的点,加上'X'和'B'和'S'和'E'之后(最多两个箱子,因此最多两个按钮,其余都"impossible"),最多有106个点,所以可以将坐标离散化,这样处理之后,对于一个状态就只要100^3了。
状态为 vis[人位置][第一个箱子位置][第二个箱子位置]。
离散化可以直接用一个二维数组标号(我NC用了map,导致跑的好慢)。
接下来就是BFS部分。
对于人的下一个位置有三种情况:
是箱子,那么要考虑箱子的下一个点是否合法,如果合法,那么人前进一格,箱子也前进一格,否则不入队。
是合法的点,直接走,入队。
不合法的点,不入队。
然后当箱子分别在不同的按钮上,并且人在终点就可以跳出BFS了。
写的又长又臭
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
struct P {
int x, y;
P () {}
P (int _x, int _y) : x(_x), y(_y) {}
bool operator < (const P &rhs) const {
if(x == rhs.x) return y < rhs.y;
return x < rhs.x;
}
} box[111*111], but[111*111], st, ed;
struct ST {
int x, y, x1, y1, x2, y2, step;
ST () {}
ST (int x, int y, int x1, int y1, int x2, int y2, int step) :
x(x), y(y), x1(x1), y1(y1), x2(x2), y2(y2), step(step) {}
};
char mp[111][111];
int n, m, ans, cbox, cbut, cnt;
bool vis[121][121][121];
map<P, int> ptoi;
map<int, P> itop;
queue<ST> que;
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};
// down, up, right, left
void init() {
for(int i = 1; i <= cbox; i++) box[i].x = 0, box[i].y = 0;
for(int i = 1; i <= cbut; i++) but[i].x = 0, but[i].y = 0;
}
int toint(int x, int y) {
return ptoi[P(x, y)];
}
P top(int x) {
return itop[x];
}
int BFS() {
memset(vis, false, sizeof(vis));
int edst = toint(ed.x, ed.y), but1st = toint(but[1].x, but[1].y), but2st = toint(but[2].x, but[2].y);
// printf("ansst : %d - %d - %d\n", edst, but1st, but2st);
while(!que.empty()) que.pop();
que.push(ST(st.x, st.y, box[1].x, box[1].y, box[2].x, box[2].y, 0));
vis[toint(st.x, st.y)][toint(box[1].x, box[1].y)][toint(box[2].x, box[2].y)] = true;
while(!que.empty()) {
ST now = que.front(); que.pop();
int x = now.x, y = now.y, x1 = now.x1, y1 = now.y1,
x2 = now.x2, y2 = now.y2, step = now.step;
if((cbut == 2 && toint(x, y) == edst && ((but1st == toint(x1, y1) && but2st == toint(x2, y2)) || (but1st == toint(x2, y2) && but2st == toint(x1, y1))))
|| (cbut == 1 && toint(x, y) == edst && (but1st == toint(x1, y1) || but1st == toint(x2, y2)))
|| (cbut == 0 && toint(x, y) == edst))
return step;
// printf("point : (%d, %d) - (%d, %d) - (%d, %d) - %d\n", x, y, x1, y1, x2, y2, step);
// printf("st : %d - %d - %d - %d\n\n", toint(x, y), toint(x1, y1), toint(x2, y2), step);
for(int i = 0; i < 4; i++) {
int nx = x + dx[i], ny = y + dy[i];
if((nx < 1 || nx > n || ny < 1 || ny > m || mp[nx][ny] == '#') && mp[nx][ny] != 'E') continue;
int stst = toint(nx, ny), b1st = toint(x1, y1), b2st = toint(x2, y2);
if(nx == x1 && ny == y1) {
int nx1 = x1 + dx[i], ny1 = y1 + dy[i];
if(nx1 < 1 || nx1 > n || ny1 < 1 || ny1 > m || mp[nx1][ny1] == '#' || (nx1 == x2 && ny1 == y2)) continue;
if(vis[toint(nx, ny)][toint(nx1, ny1)][toint(x2, y2)]) continue;
vis[toint(nx, ny)][toint(nx1, ny1)][toint(x2, y2)] = true;
que.push(ST(nx, ny, nx1, ny1, x2, y2, step + 1));
} else if(nx == x2 && ny == y2) {
int nx2 = x2 + dx[i], ny2 = y2 + dy[i];
if(nx2 < 1 || nx2 > n || ny2 < 1 || ny2 > m || mp[nx2][ny2] == '#' || (nx2 == x1 && ny2 == y1)) continue;
if(vis[toint(nx, ny)][toint(x1, y1)][toint(nx2, ny2)]) continue;
vis[toint(nx, ny)][toint(x1, y1)][toint(nx2, ny2)] = true;
que.push(ST(nx, ny, x1, y1, nx2, ny2, step + 1));
} else {
if(vis[toint(nx, ny)][toint(x1, y1)][toint(x2, y2)]) continue;
vis[toint(nx, ny)][toint(x1, y1)][toint(x2, y2)] = true;
que.push(ST(nx, ny, x1, y1, x2, y2, step + 1));
}
}
}
return -1;
}
int main() {
int t; scanf("%d", &t);
while(t--) {
ptoi.clear(); itop.clear();
scanf("%d%d", &n, &m);
cbox = 0, cbut = 0, cnt = 0;
for(int i = 1; i <= n; i++) {
scanf(" %s", mp[i] + 1);
for(int j = 1; j <= m; j++) {
if(mp[i][j] != '#') ptoi[P(i, j)] = ++cnt, itop[cnt] = P(i, j);
if(mp[i][j] == 'S') st.x = i, st.y = j;
else if(mp[i][j] == 'E') ed.x = i, ed.y = j;
else if(mp[i][j] == 'X') box[++cbox].x = i, box[cbox].y = j;
else if(mp[i][j] == 'B') but[++cbut].x = i, but[cbut].y = j;
}
}
if(cbut > cbox) { puts("impossible"); init(); continue; }
// puts("------begin BFS------");
ans = BFS();
if(~ans) printf("%d\n", ans);
else puts("impossible");
init();
}
return 0;
}
/*
8
7 8
########
#..S...#
#.####.#
#.#.XB.#
#.####.#
#......E
########
7 8
########
#..S...#
#.####.#
#.#.BX.#
#.####.#
#......E
########
4 8
##E#####
#...####
#SX.XBB#
########
7 8
########
#...S###
#.##.###
#.X.X.B#
#.##.###
#....###
####E###
7 8
########
#...S###
#.##.###
#.X.XBB#
#.##.###
#....###
####E###
7 7
#######
#....##
#.##.##
#.SXXB#
#.##.##
#....##
#E#####
6 7
#######
###...#
###.#.#
#S.X..E
###B###
#######
5 5
#####
#BXB#
#S#XE
#...#
#####
---
im
10
19
23
24
19
im
*/
Codeforces Gym101518E:The Pharaoh's Curse(BFS + 离散化)的更多相关文章
- Codeforces Gym 100187E E. Two Labyrinths bfs
E. Two Labyrinths Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/prob ...
- CodeForces 55D "Beautiful numbers"(数位DP+离散化处理)
传送门 参考资料: [1]:CodeForces 55D Beautiful numbers(数位dp&&离散化) 我的理解: 起初,我先定义一个三维数组 dp[ i ][ j ][ ...
- CodeForces - 516B Drazil and Tiles(bfs)
https://vjudge.net/problem/CodeForces-516B 题意 在一个n*m图中放1*2或者2*1的长方形,问是否存在唯一的方法填满图中的‘.’ 分析 如果要有唯一的方案, ...
- hdu 2771(uva 12171) Sculpture bfs+离散化
题意: 给出一些边平行于坐标轴的长方体,这些长方体可能相交.也可能相互嵌套.这些长方体形成了一个雕塑,求这个雕塑的整体积和表面积. 题解: 最easy想到直接进行bfs或者dfs统计,但此题的麻烦之处 ...
- CodeForces - 616C(很有意思的bfs,set,map的使用)
传送门: http://codeforces.com/problemset/problem/616/C C. The Labyrinth time limit per test 1 second me ...
- CodeForces - 580C Kefa and Park 【BFS】
题目链接 http://codeforces.com/problemset/problem/580/C 题意 根节点是 1 然后所有的叶子结点都是饭店 从根节点到叶子结点的路径上 如果存在 大于m 个 ...
- Codeforces 659F Polycarp and Hay【BFS】
有毒,自从上次选拔赛(哭哭)一个垃圾bfs写错之后,每次写bfs都要WA几发...好吧,其实也就这一次... 小白说的对,还是代码能力不足... 非常不足... 题目链接: http://codefo ...
- Codeforces 677D Vanya and Treasure 暴力+BFS
链接 Codeforces 677D Vanya and Treasure 题意 n*m中有p个type,经过了任意一个 type=i 的各自才能打开 type=i+1 的钥匙,最初有type=1的钥 ...
- codeforces 591 E. Three States(bfs+思维)
题目链接:http://codeforces.com/contest/591/problem/E 题意:有3个数字表示3个城市,每种城市都是相互连通的,然后不同种的城市不一定联通,'.'表示可以建设道 ...
随机推荐
- Matlab随笔之指派问题的整数规划
原文:Matlab随笔之指派问题的整数规划 注:除了指派问题外,一般的整数规划问题无法直接利用Matlab函数,必须Matlab编程实现分支定界法和割平面解法. 常用Lingo等专用软件求解整数规划问 ...
- XDEBUG+PHPSTORM 开发 调试
原文:XDEBUG+PHPSTORM 开发 调试 XDEBUG+PHPSTORM 开发 调试 在我们开发过程中.我们如果经常性的echo.dump效率很低.所以我们就可以使用xdebug进行断点调试. ...
- mysql重置root密码,并设置可远程访问
linux系统: mysqld_safe --skip-grant-tables & mysql -u root use mysql UPDATE user SET host = '%' wh ...
- EasyUI-DataGrid多线动态实现选择性合并
jQuery EasyUI有一个非常易于使用的数据列表控件,这是DataGrid控制.某些背景json格式可以传递给在前景中显示的控制,很强大.只要有时需求须要这样即多行合并,如在列表中假设同样的部门 ...
- 在实现视频播放器的步骤client(三)风行网络电影列表
(三) 今日热门电影实现这个功能.主要从server获取数据.然后显示在屏幕上.虽然说是从这个server获取电影信息数据,但,不实际的http相关知识,我们直接sdk包(56网络提供api),你将能 ...
- Spring MVC专题
Spring从3.1版本开始增加了ConfigurableEnvironment和PropertySource: ConfigurableEnvironment Spring的ApplicationC ...
- Win8 Metro(C#)数字图像处理--2.61哈哈镜效果
原文:Win8 Metro(C#)数字图像处理--2.61哈哈镜效果 [函数名称] 哈哈镜效果函数 WriteableBitmap DistortingMirrorProcess(Writea ...
- 使用 Visual Studio 开发并调试 Mail Add-in (mail app for Outlook)
准备工作 如果你的邮箱搭建在 Exchange Server 上,则可以创建邮件应用程序(Mail Add-in)来扩展Office本身的功能,使用 Office Add-in Model 开发的 M ...
- SpringMVC与uploadify结合进行上传
uploadify是一个第三方js插件,支持多文件上传,拥有较为强大的上传功能 1.uploadify实现 下载其flash版本 http://www.uploadify.com/ 解压后将其内容区 ...
- UILabel实现自适应宽高需要注意的地方
需求如下: 需要显示2行文字,宽度为 SCREEN_Width - 40 高度为两行文本的自适应高度 需要在此UILabel 下面添加imageView , 因此UIlabel 的高度需要准确,不 ...