[UVa 1601] The Morning after Halloween (双向广搜)
来源:互联网 发布:java中get(class) 编辑:程序博客网 时间:2024/05/16 01:50
链接
UVa 1601
题意
类似“推箱子”,将n个小写字母推到对应的大写字母的位置。每一步对每个小写字母可推最多一次,且不可发生冲突。
题解
将“局势”看做状态,就是一道隐式图搜索,但是状态数比较多,时间上还是挺紧的。
由于有>1/4的格子都是障碍物,可以将可走的格子抽出单独建图,邻接表存储,再广搜即可。
在此基础上可以将算法改进为双向广搜,这样速度更快(实测快了有一倍)。
双向广搜有个坑,就是要正反向每次扩展一层(而不是一个节点),否侧会漏解。
为了防止退化,可以按照正向和反向的节点数量决定下一层扩展正向or反向(实测确实更快了)。
代码
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <vector>#include <queue>using namespace std;char g[20][20];int w, h, n, st[3], ed[3], cnt, idx[20][20], locate[1<<8], dx[4] = { 1, -1, 0, 0 }, dy[4] = { 0, 0, 1, -1 };const int inf = 1e9 + 7;vector<int> to[20 * 20];void init(){ for(int i = 0; i < h; i++) gets(g[i]); cnt = 0; for(int i = 0, k = 0; i < h; i++) for(int j = 0; j < w; j++) if(g[i][j] != '#') { idx[i][j] = ++cnt; to[cnt].clear(); to[cnt].push_back(cnt); if(isupper(g[i][j])) { locate[g[i][j]] = k++; } } for(int i = 0; i < h; i++) for(int j = 0; j < w; j++) if(g[i][j] != '#') { if(isupper(g[i][j])) { ed[locate[g[i][j]]] = idx[i][j]; } if(islower(g[i][j])) { st[locate[toupper(g[i][j])]] = idx[i][j]; } for(int k = 0, a, b; k < 4; k++) { a = i + dx[k], b = j + dy[k]; if(a >= 0 && a < h && b >= 0 && b < w && g[a][b] != '#') to[idx[i][j]].push_back(idx[a][b]); } } to[cnt + 1].clear(); to[cnt + 1].push_back(cnt + 1); to[cnt + 2].clear(); to[cnt + 2].push_back(cnt + 2); if(n == 1) { st[1] = ++cnt; ed[1] = st[1]; st[2] = ++cnt; ed[2] = st[2]; } if(n == 2) { st[2] = ++cnt; ed[2] = st[2]; }}struct Node { int v[3], d; Node(int a, int b, int c, int _d) { v[0] = a, v[1] = b, v[2] = c; d = _d; }};queue<Node> que[2];int dis[2][1<<8][1<<8][1<<8], num[2];bool check(int a, int b, int c, int i, int j, int k){ if(a == b || b == c || c == a) return false; if(b == i && a == j || b == k && c == j || c == i && a == k) return false; return true;}int bfs(){ int ans = inf; memset(dis, -1, sizeof(dis)); while(!que[0].empty()) que[0].pop(); num[0] = 1; while(!que[1].empty()) que[1].pop(); num[1] = 1; que[0].push(Node(st[0], st[1], st[2], 0)); dis[0][st[0]][st[1]][st[2]] = 0; que[1].push(Node(ed[0], ed[1], ed[2], 0)); dis[1][ed[0]][ed[1]][ed[2]] = 0; while(!que[0].empty() && !que[1].empty()) { int x = int(num[0] > num[1]), y = int(num[0] <= num[1]); int dep = que[x].front().d; while(!que[x].empty() && que[x].front().d == dep) { Node now = que[x].front(); que[x].pop(); if(dis[y][now.v[0]][now.v[1]][now.v[2]] >= 0) { return now.d + dis[y][now.v[0]][now.v[1]][now.v[2]]; } for(int i = 0, a; i < to[now.v[0]].size(); i++) { a = to[now.v[0]][i]; for(int j = 0, b; j < to[now.v[1]].size(); j++) { b = to[now.v[1]][j]; for(int k = 0, c; k < to[now.v[2]].size(); k++) { c = to[now.v[2]][k]; if(check(a, b, c, now.v[0], now.v[1], now.v[2]) && dis[x][a][b][c] < 0) { dis[x][a][b][c] = now.d + 1; que[x].push(Node(a, b, c, now.d + 1)); num[x]++; } } } } } } return -1;}int main(){ //freopen("in.txt", "r", stdin); while(cin >> w >> h >> n) { if(w + h + n == 0) break; while(getchar() != '\n') continue; init(); cout << bfs() << endl; } return 0;}
0 0
- [UVa 1601] The Morning after Halloween (双向广搜)
- UVa 1601 - The Morning after Halloween(双向BFS版)
- UVa 1601 The morning after Halloween(单向BFS+双向BFS)
- 例题7-9 UVA - 1601 && POJ 3523 The Morning after Halloween (双向BFS)
- UVA 1601 POJ 3523 The Morning after Halloween 【双向BFS】【A*】 (好题)
- 隐式图--UVA - 1601 The Morning after Halloween
- UVa OJ 1601 - The Morning after Halloween
- UVA 1601 The Morning after Halloween [DBFS]
- uva 1601 The Morning after Halloween
- uva 1601 The Morning after Halloween code2
- UVa #1601 The Morning after Halloween (例题7-9)
- UVa 1601 - The Morning after Halloween(单向BFS版)
- UVa 1601:The Morning after Halloween(BFS)
- UVA 1601 The Morning after Halloween (优化BFS)
- The Morning after Halloween UVA
- The Morning after Halloween UVA
- 1601 - The Morning after Halloween(BFS)
- 1601 - The Morning after Halloween
- redis中redis.conf配置文件解析
- 借鉴flash例程
- hdu2096 小明A+B
- JNI中参数的传递与操作
- js判断pc还是mobile访问
- [UVa 1601] The Morning after Halloween (双向广搜)
- Linux mtd system
- svn 更新代码和上传代码
- servlet单例多线程一
- xamarin.iOS 设置Label指定文字的颜色
- gstreamer学习笔记:通过udp传输音视频
- 使用C#强制转化日期
- RNN以及LSTM的介绍和公式梳理
- Java泛型之Type体系