题目链接

题意

给出一个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部分。

对于人的下一个位置有三种情况:

  1. 是箱子,那么要考虑箱子的下一个点是否合法,如果合法,那么人前进一格,箱子也前进一格,否则不入队。

  2. 是合法的点,直接走,入队。

  3. 不合法的点,不入队。

然后当箱子分别在不同的按钮上,并且人在终点就可以跳出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 + 离散化)的更多相关文章

  1. Codeforces Gym 100187E E. Two Labyrinths bfs

    E. Two Labyrinths Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/prob ...

  2. CodeForces 55D "Beautiful numbers"(数位DP+离散化处理)

    传送门 参考资料: [1]:CodeForces 55D Beautiful numbers(数位dp&&离散化) 我的理解: 起初,我先定义一个三维数组 dp[ i ][ j ][ ...

  3. CodeForces - 516B Drazil and Tiles(bfs)

    https://vjudge.net/problem/CodeForces-516B 题意 在一个n*m图中放1*2或者2*1的长方形,问是否存在唯一的方法填满图中的‘.’ 分析 如果要有唯一的方案, ...

  4. hdu 2771(uva 12171) Sculpture bfs+离散化

    题意: 给出一些边平行于坐标轴的长方体,这些长方体可能相交.也可能相互嵌套.这些长方体形成了一个雕塑,求这个雕塑的整体积和表面积. 题解: 最easy想到直接进行bfs或者dfs统计,但此题的麻烦之处 ...

  5. CodeForces - 616C(很有意思的bfs,set,map的使用)

    传送门: http://codeforces.com/problemset/problem/616/C C. The Labyrinth time limit per test 1 second me ...

  6. CodeForces - 580C Kefa and Park 【BFS】

    题目链接 http://codeforces.com/problemset/problem/580/C 题意 根节点是 1 然后所有的叶子结点都是饭店 从根节点到叶子结点的路径上 如果存在 大于m 个 ...

  7. Codeforces 659F Polycarp and Hay【BFS】

    有毒,自从上次选拔赛(哭哭)一个垃圾bfs写错之后,每次写bfs都要WA几发...好吧,其实也就这一次... 小白说的对,还是代码能力不足... 非常不足... 题目链接: http://codefo ...

  8. Codeforces 677D Vanya and Treasure 暴力+BFS

    链接 Codeforces 677D Vanya and Treasure 题意 n*m中有p个type,经过了任意一个 type=i 的各自才能打开 type=i+1 的钥匙,最初有type=1的钥 ...

  9. codeforces 591 E. Three States(bfs+思维)

    题目链接:http://codeforces.com/contest/591/problem/E 题意:有3个数字表示3个城市,每种城市都是相互连通的,然后不同种的城市不一定联通,'.'表示可以建设道 ...

随机推荐

  1. Matlab随笔之插值与拟合(下)

    原文:Matlab随笔之插值与拟合(下) 1.二维插值之插值节点为网格节点 已知m x n个节点:(xi,yj,zij)(i=1…m,j=1…n),且xi,yi递增.求(x,y)处的插值z. Matl ...

  2. 好用的Markdown 编辑器及工具

    Markdown 是 2004 年由 John Gruberis 设计和开发的纯文本格式的语法,所以通过同一个名字它可以使用工具来转换成 HTML.readme 文件,在线论坛编写消息和快速创建富文本 ...

  3. js,css引用顺序设定

    遇到的困难 在ASP .NET MVC里面,会使用_Layout.cshtml来绘制一些全局的公共页面,以及引用相关的css和js而在每个独立的页面中,也有自己独立的js一般来说,希望公共的js放在独 ...

  4. window对象的方法

    window.alert('大家好!');//弹出警告对话框 window.confirm('确定要删除吗?');//确定.取消对话框,返回true或false; window.navigate(ur ...

  5. ubuntu16.04安装搜狗输入法

    安装完Ubuntu 16.04后,要更换为国内的软件源: Ali-OSM Alibaba Open Source Mirror Site Home About Join Us Ubuntu 1.软件包 ...

  6. Cordova 教程地址

    原文:Cordova 教程地址 1.Cordova 官网 http://cordova.apache.org/ 2.Cordova插件库 for android http://cordova.apac ...

  7. Editor.md v1.4.2 发布,改进自定义工具栏

    分享 <关于我> 分享  [中文纪录片]互联网时代                 http://pan.baidu.com/s/1qWkJfcS 分享 <HTML开发MacOSAp ...

  8. 关于Eurekalog解决不能发邮件的问题

    最近无意中发现在盒子论坛中有人回答了本文的问题,最后在Eurekalog的安装目录中的ExceptionLog.pas找到了多发送的Rest命令的地方,现传上来,有需要的朋友下载下面的文件. 因为16 ...

  9. 针对TianvCms的搜索优化文章源码(无版权, 随便用)

    介绍: 搜索优化虽然不是什么高深的技术, 真正实施起来却很繁琐, 后台集成搜索优化的文章可以便于便于管理, 也让新手更明白优化的步奏以及优化的日常. 特点: 根据自己的经验和查阅各种资料整理而成, 相 ...

  10. Jstack线程状态BLOCKED/TIMED_WAITING/WAITING解释

    一.线程5种状态 新建状态(New) 新创建了一个线程对象. 就绪状态(Runnable) 线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运行,等待获 ...