Abbott 的復仇(Abbott's Revenge,ACM|IPPC World Finals 2000, UVa 816)

代碼如下:

#include <iostream>
#include <queue>
using namespace std;

//const char * dirs = "NESW";
//const char * turns = "FLR";
const int N = 0, E = 1, S = 2, W = 3;
const int F = 0, L = 1, R = 2;

//分別表示N(上),E(右),S(下),W(左)
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};

//移動的角色有三個屬性(行,列,方向)
typedef struct Node
{
	Node(){}
	Node(int row, int col, int d):r(row), c(col), dir(d){}
	int r;
	int c;
	int dir;
}Node;

int END_POINT_ROW = 3;
int END_POINT_COL = 3;

/*
 *p[0][0][]的情況是浪費的空間,因爲座標是從p[1][1][]開始; 
 *d[0][0][]的情況是浪費的空間,因爲座標是從d[1][1][]開始
 *has_edge[0][0][]的情況是浪費的空間,因爲座標是從has_edge[1][1][][]開始
 */
Node p[4][4][4];	//保存的是父節點(行,列,方向);建立終點往回找的線索
int d[4][4][4];		//標記當前節點是否走過
bool has_edge[4][4][4][3] = {0};	//保存角色下一步能走的方向(FLR)

//判斷角色是否越界了
bool inside(int r, int c)
{
	if(3 == r && 1 == c || 3 == r && 3 == c) return true;
	if(r >= 1 && r <= 2 && c >= 1 && c <= 3) return true;
	return false;
}

//通過前一點的移動方向,得到下一點的位置
Node walk(const Node &u, int turn)
{
	int dir = u.dir;
	if(turn == 1) dir = (dir + 3) % 4;
	if(turn == 2) dir = (dir + 1) % 4;
	return Node(u.r + dr[dir], u.c + dc[dir], dir);
}

//從終點開始回溯查找起點,並從起點開始打印走過的路
void print_ans(Node u)
{
	vector<Node> nodes;
	for(;;)
	{
		nodes.push_back(u);
		if(d[u.r][u.c][u.dir] == 0) break;
		u = p[u.r][u.c][u.dir];
	}
	//nodes.push_back(Node(r0, c0, dir));
	Node nodeBegin(3, 1, N);
	nodes.push_back(nodeBegin);

	int cnt = 0;
	for(int i = nodes.size() - 1; i >= 0; i--)
	{
		if(cnt % 10 == 0) printf(" ");
		printf(" (%d,%d)", nodes[i].r, nodes[i].c);
		if(++cnt % 10 == 0) printf("\n");
	}
	if(nodes.size() % 10 != 0) printf("\n");
}

void solve()
{
	queue<Node> q;
	memset(d, -1, sizeof(d));
	//Node u(r1, c1, dir);
	Node u(2, 1, N);
	d[u.r][u.c][u.dir] = 0;
	q.push(u);
	while(!q.empty())
	{
		Node u = q.front(); q.pop();
		if(u.r == END_POINT_ROW && u.c == END_POINT_COL) { print_ans(u); return;}
		for(int i = 0; i < 3; i++)
		{
			Node v = walk(u, i);
			if(has_edge[u.r][u.c][u.dir][i] && inside(v.r, v.c)
					&& d[v.r][v.c][v.dir] < 0)
			{
				d[v.r][v.c][v.dir] = d[u.r][u.c][u.dir] + 1;
				p[v.r][v.c][v.dir] = u;
				q.push(v);
			}
		}
	}
	printf("No Soulution\n");
}

int main()
{
	memset(has_edge, 0, sizeof(has_edge));
	//設置約束條件,規定在某個點上,角色只能往某幾個方向走
	//如下,規定(3,1)朝北的角色只能向前(F)走
	has_edge[3][1][N][F] = true;

	has_edge[2][1][N][F] = true; 
	has_edge[2][1][S][L] = true; 
	has_edge[2][1][W][R] = true; 

	has_edge[1][1][N][R] = true; 
	has_edge[1][1][W][L] = true; 

	has_edge[1][2][E][R] = true; 
	has_edge[1][2][W][F] = true; 
	has_edge[1][2][W][L] = true; 
	has_edge[1][2][N][R] = true; 

	has_edge[2][2][E][F] = true; 
	has_edge[2][2][E][L] = true; 
	has_edge[2][2][S][L] = true; 
	has_edge[2][2][W][F] = true; 

	has_edge[1][3][E][R] = true; 
	has_edge[1][3][N][L] = true; 

	has_edge[2][3][E][L] = true; 
	has_edge[2][3][S][F] = true; 
	has_edge[2][3][S][R] = true; 

	has_edge[3][3][S][F] = true; 
	solve();
	return 0;
}

輸出:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章