Abbott’s Revenge UVa816 WorldFinal2000

题意简述: 从不同方向(北N, 东E, 南S, 西W)进入迷宫的任意位置,只能走向指定的几个方向(前进F, 左转L, 右转R)。给定起点及方向、终点,要求输出最短路径。输入输出格式见原题。
题解:用BFS求最短路径,三维数组(row, col, dir)记录节点信息,四维数组(row, col, dir, turn)记录移动信息。注意初始化等细节。//代码输出行的缩进格式未控制
//Abbott's Revenge
//Yhq
#include<iostream>
#include<string>
#include<sstream>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
struct Node;
const char DIR[]={'N', 'E', 'S', 'W'};
const char TURN[]={'F', 'L', 'R'};
int c_to_dir(char ch) {
	switch (ch) {
		case 'N': return 0;
		case 'E': return 1;
		case 'S': return 2;
		case 'W': return 3;
	}
}
int c_to_turn(char ch) {
	switch (ch) {
		case 'F': return 0;
		case 'L': return 1;
		case 'R': return 2;
	}
}

bool possib[10][10][4][3]={0}; //possibility[row][col][dir][turn]
bool hasR[10][10][4]={0}; //has reached [row][col][dir]

struct Node{
	int row, col, dir;
	Node() {}
	Node(int r, int c, int d): row(r), col(c), dir(d) {}
	bool operator == (const Node& u) {
		return row==u.row && col==u.col && dir==u.dir;
	}
};
Node start, end;
Node lastNode[10][10][4];

//walking from u to a new node
const int row_dir[]={-1, 0, 1, 0};
const int col_dir[]={0, 1, 0, -1};
Node walk (const Node& u, int turn) {
	int resdir = u.dir;
	if (turn==1) resdir+=3; //attention to mod!
	else if (turn==2) resdir++;
	resdir = resdir%4;
	return Node(u.row+row_dir[resdir], u.col+col_dir[resdir], resdir);
}

void input() {
	char startdir;
	cin>>start.row>>start.col>>startdir>>end.row>>end.col;
	start.dir = c_to_dir(startdir);
	string str;
	while (getline(cin,str)) {
		if (str[0]=='0') return;
		int r, c;
		stringstream ss(str);
		ss>>r;
		ss>>c;
		string s;
		while (ss>>s) {
			if (s=="*") break;
			int d=c_to_dir(s[0]);
			for (int i=1; i<s.length(); ++i) possib[r][c][d][c_to_turn(s[i])]=true;
		}
	}
}
void print(Node);
void solve () {
	queue<Node> que;
	Node u = walk(start,0);
	lastNode[u.row][u.col][u.dir]=start;
	que.push(u);
	hasR[u.row][u.col][u.dir]=true;
	while (!que.empty()) {
		Node u0=que.front();
		que.pop();
		//if (que.empty()) cout<<"empty now"<<endl;
		if (u0.row==end.row && u0.col==end.col) {
			print(u0);
			return;
		}
		for (int i=0; i<3; ++i) {
			if (possib[u0.row][u0.col][u0.dir][i]) {
				//cout<<"possible: "<<i<<endl;
				Node newnode=walk(u0,i);
				if (!hasR[newnode.row][newnode.col][newnode.dir]) {
					hasR[newnode.row][newnode.col][newnode.dir]=true;
					lastNode[newnode.row][newnode.col][newnode.dir]=u0;
					que.push(newnode);
					//print(newnode);
				}
			}
		}
	}
	cout<<"No Solution Possible"<<endl;
}
void print (Node u) {
	vector<Node> vec;
	Node temp = u;
	while (1) {
		vec.push_back(temp);
		if (temp==start) break;
		temp=lastNode[temp.row][temp.col][temp.dir];
	}
	for (int i=vec.size()-1; i>=0; --i) {
		cout<<"("<<vec[i].row<<","<<vec[i].col<<")";
		if (i!=0) cout<<" ";
		else cout<<endl;
	}
}
void reset() {
	memset(possib,false,sizeof(possib));
	memset(hasR,false,sizeof(hasR));
}
int main () {
	string name;
	while (cin>>name) {
		if (name=="END") return 0;
		reset();
		input();
		cout<<name<<endl;
		solve();
	}
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值