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

  • Post author:
  • Post category:其他



复杂的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;
}



版权声明:本文为acraz原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。