您的位置:首页 > 其它

UVa 816 Abbott's Revenge(状态压缩BFS)

2015-09-01 15:11 323 查看
复杂的BFS:求最短路,但是每个点能转的方向是有限制的。

把一个点的状态扩展为4个状态分别表示在该点时面向哪一面.

#pragma warning(disable:4996)
#include <iostream>
#include <cstdio>
#include <string>
#include <queue>
#include <cstring>
#include <vector>
using namespace std;

struct node{
//定义状态:该题目不是每一个点是一个状态,
//而是扩展到了每一个点面朝的方向都是一个状态
node(){}
node(int a, int b, int c) :r(a), c(b), dir(c){}
int r, c, dir;
};

int d[10][10][4];//表示d[r][c][dir]到达状态(r,c,dir)的最短距离,顺便当做vis数组标记访问情况
node p[10][10][4];//表示状态(r,c,dir)的前驱
bool has_edge[10][10][4][3];
node now;
int R, C;//终点
int DIR[4][2] = { -1, 0, 0, 1, 1, 0, 0, -1 };//方向数组
bool inside[10][10];

node turn(node t, int type){
int d = t.dir;
if (type == 1){
d--;
if (d == -1)d = 3;
}
else if (type == 2){
d++;
if (d == 4)d = 0;
}
return node(t.r + DIR[d][0], t.c + DIR[d][1], d);
}

bool bfs(){
queue<node>q;
memset(d, -1, sizeof d);
d[now.r][now.c][now.dir] = 0;
q.push(now);
while (!q.empty()){
now = q.front(); q.pop();
if (now.r == R&&now.c == C)return true;//此时沿着p数组从now开始找路径
//now出来的可能的三个方向
for (int i = 0; i<3; i++){
node nxt = turn(now, i);
if (inside[nxt.r][nxt.c] && has_edge[now.r][now.c][now.dir][i] && d[nxt.r][nxt.c][nxt.dir] == -1){
d[nxt.r][nxt.c][nxt.dir] = d[now.r][now.c][now.dir] + 1;
p[nxt.r][nxt.c][nxt.dir] = now;
q.push(nxt);
}
}

}
return false;
}

inline int get(char ch){
if (ch == 'N' || ch == 'F')return 0;
else if (ch == 'E' || ch == 'L')return 1;
else if (ch == 'S' || ch == 'R')return 2;
else if (ch == 'W')return 3;
return -1;
}

int main(){

//freopen("in.txt", "r", stdin);

string name;
char ch;
node start;
while (cin >> name){
if (name == "END")break;
memset(inside, false, sizeof inside);
memset(p, 0, sizeof p);
memset(has_edge, false, sizeof has_edge);

cin >> start.r >> start.c >> ch >> R >> C;
inside[start.r][start.c] = inside[R][C] = true;
start.dir = get(ch);
now.dir = start.dir;
now.r = start.r + DIR[now.dir][0];
now.c = start.c + DIR[now.dir][1];
int x, y;
while (cin >> x){
if (x == 0)break;
cin >> y;
inside[x][y] = true;
string s;
while (cin >> s){
if (s[0] == '*')break;
int d = get(s[0]);
for (int i = 1; i < (int)s.size(); i++){
has_edge[x][y][d][get(s[i])] = true;
}
}
}
cout << name << endl;
if (inside[now.r][now.c] && bfs()){
vector<node>ans;
while (true){
ans.push_back(now);
if (d[now.r][now.c][now.dir] == 0){
ans.push_back(start);
break;
}
now = p[now.r][now.c][now.dir];
}
int cnt = 0;
for (int i = (int)ans.size() - 1; i >= 0; i--){
if (cnt % 10 == 0)printf(" ");
printf(" (%d,%d)", ans[i].r, ans[i].c);
if (++cnt % 10 == 0)puts("");
}
if ((int)ans.size() % 10 != 0)puts("");
}
else{
printf("  No Solution Possible\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: