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个城市,每种城市都是相互连通的,然后不同种的城市不一定联通,'.'表示可以建设道 ...
随机推荐
- Jmeter 专题
Jmeter是一个非常好用的压力测试工具. Jmeter用来做轻量级的压力测试,非常合适,只需要十几分钟,就能把压力测试需要的脚本写好. 为什么要建立线程组?原因很简单,因为我们要模拟多个线程(用户 ...
- Android各版本对应的SDK和JDK版本
原文:Android各版本对应的SDK和JDK版本 一.Android各版本对应的SDK版本: 平台版本 SDK版本 版本名称 Android 8.0 26 Oreo Android 7.1 25 N ...
- C#代码中设置 控件的触发器
Style style = new Style(); style.TargetType = typeof(TextBox); MultiDataTrigger trigger = new MultiD ...
- C++调用Python浅析
环境 VS2005Python2.5.4 Windows XP SP3 简述 一般开发过游戏的都知道Lua和C++可以很好的结合在一起,取长补短,把Lua脚本当成类似动态链接库来使用,很好的利用了脚本 ...
- UWP开发学习笔记3
获取可视化状态列表 private void Button_Click(object sender, RoutedEventArgs e) { //获取CheckBox控件可视化树中的子元素数量 in ...
- UWP应用使用SQLite库的方法
1.打开菜单“工具”-“扩展和更新”,选择“联机”选项,然后搜索“SQLite”,在搜索结果中找到“SQLite for Universal Windows Platform”,然后点击下载进行安装. ...
- SignalR的简单实现(一)
原文:SignalR的简单实现(一) ASP.NET SignalR是ASP.NET开发人员的一个新库,它使您的应用程序添加实时Web功能变得非常简单.什么是"实时网络"功能?能够 ...
- 传入字典的模型项的类型为“System.Boolean”,但此字典需要类型“InternalCRM.EntityIACrm.Template”的模型项。
“/”应用程序中的服务器错误. 传入字典的模型项的类型为“System.Boolean”,但此字典需要类型“InternalCRM.EntityIACrm.Template”的模型项. 说明: 执行当 ...
- 了解Service
多线程编程: 线程的基本用法: 1. class MyThread extends Thread{ @Override public void run() { //处理具体逻辑 } } new MyT ...
- SQLite的使用(包括编译安装的步骤)
SQLite官网http://www.sqlite.org/ SQLite简介 SQLite是一款轻型的数据库,是遵守ACID(原子性.一致性.隔离性和持久性)的关系式数据库管理系统.SQLite实现 ...