UVa 810 筛子难题(A Dicey Problem)

题目:
走迷宫,筛子头上的那个数字和将要走的位置的数字相同就可以走。
给的是头和面对我们的两个数字,根据折叠的那张图。
就可以推出来筛子长什么样。

要点:

  • 一个位置被访问的条件是 在这个点骰子是一样的,即不能只依靠某个点确认是否走过,还要看骰子走到这个点的状态,来确定这个点是否走过

额。本题我写的非常麻烦,但是易懂。代码很长,但基本都有注释。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 10 + 10;
int pic[maxn][maxn];
int r, c, beginX, beginY, top, _forward;
int bottom, _left, _right, _back;
int confirmLeft[7][7];
bool vis[maxn][maxn][7][7]; //以36种方式访问

struct Node {
	int x, y;
	Node* parent;
	int left, right, top, bottom, forward, back;
	Node() {}
	Node(int x, int y, Node* root) :x(x), y(y), parent(root) {}
};

//初始化确认左数组
void initArr() {
	confirmLeft[5][1] = 3; confirmLeft[1][2] = 3; confirmLeft[2][6] = 3; confirmLeft[6][5] = 3;
	confirmLeft[1][5] = 4; confirmLeft[2][1] = 4; confirmLeft[6][2] = 4; confirmLeft[5][6] = 4;
	confirmLeft[2][3] = 1; confirmLeft[3][5] = 1; confirmLeft[5][4] = 1; confirmLeft[4][2] = 1;
	confirmLeft[3][2] = 6; confirmLeft[5][3] = 6; confirmLeft[4][5] = 6; confirmLeft[2][4] = 6;
	confirmLeft[4][6] = 2; confirmLeft[6][3] = 2; confirmLeft[3][1] = 2; confirmLeft[1][4] = 2;
	confirmLeft[6][4] = 5; confirmLeft[3][6] = 5; confirmLeft[1][3] = 5; confirmLeft[4][1] = 5;
}
//输入及确定骰子
void init() {
	memset(vis, 0, sizeof(vis));
	cin >> r >> c >> beginX >> beginY >> top >> _forward;
	for (int i = 1; i <= r; i++) {
		for (int j = 1; j <= c; j++) {
			cin >> pic[i][j];
		}
	}
	// 确定骰子
	_back = 7 - _forward;
	bottom = 7 - top;
	_left = confirmLeft[top][_forward];
	_right = 7 - _left;
}
//i = 1, 2, 3, 4 表示上 左 右 下
void turnDir(int i, int& top, int& bottom, int& left, int& right, int& forward, int& back, int& x, int& y) {
	int temp;
	//向下 
	if (i == 1) { temp = bottom; bottom = forward; forward = top; top = back; back = temp; x++;}
	//向右
	if (i == 2) { temp = bottom; bottom = left; left = top; top = right; right = temp; y--;}
	//向左
	if (i == 3) {temp = bottom; bottom = right; right = top; top = left; left = temp; y++;}
	//向上
	if (i == 4) {temp = bottom; bottom = back; back = top; top = forward; forward = temp; x--;}
}

int cnt = 0;
int size1 = 0;
void getSize(Node* root) {
	while (root ->parent) {
		size1++;
		root = root->parent;
	}
}
//(1,2),(2,2),(2,3),(3,3),(3,2),(3,1),(2,1),(1,1),(1,2)
void print(Node* root) {
	if (root == NULL) return;
	print(root->parent);
	if (cnt % 9 == 0 && cnt)
		cout << endl;
	if(cnt % 9 == 0)
	cout << "  (" << root->x << "," << root->y << ")";
	else
	cout << "(" << root->x << "," << root->y << ")";
	if (cnt != size1)
		cout << ",";
	cnt++;
}

bool bfs() {
	size1 = 0;
	cnt = 0;
	queue<Node*> q;
	Node* root = new Node(beginX, beginY, NULL);
	root->back = _back;
	root->bottom = bottom;
	root->forward = _forward;
	root->top = top;
	root->left = _left;
	root->right = _right;
	q.push(root);
	bool begin = false;
	while (!q.empty()) {
		Node* temp = q.front();
		q.pop();
		//cout << temp->x << " " << temp->y << endl;
		//cout << temp->top << endl;
		if (temp->x == beginX && temp->y == beginY && begin) {
			getSize(temp);
			print(temp);
			return true;
		}
		for (int i = 1; i <= 4; i++) {
			Node* temp2 = new Node();
			temp2->back = temp->back; temp2->bottom = temp->bottom;
			temp2->forward = temp->forward; temp2->left = temp->left;
			temp2->parent = temp2->parent; temp2->right = temp->right;
			temp2->top = temp->top; temp2->x = temp->x; temp2->y = temp->y;
			turnDir(i, temp2->top, temp2->bottom, temp2->left, temp2->right,
				temp2->forward, temp2->back, temp2->x, temp2->y);
			if (temp2->x < 1 || temp2->x > r || temp2->y < 1
				|| temp2->y > c || pic[temp2->x][temp2->y] == 0) continue;
			if (temp->top != pic[temp2->x][temp2->y]
				&& pic[temp2->x][temp2->y] != -1) continue;
			if (!vis[temp2->x][temp2->y][temp2->top][temp2->forward]) {
				q.push(temp2);
				temp2->parent = temp;
				vis[temp2->x][temp2->y][temp2->top][temp2->forward] = 1;
			}
		}
		begin = true;
	}
	return false;
}

int main() {
	initArr();
	string s;
	while (cin >> s && s != "END") {
		init();
		Node root;
		cout << s << endl;
		if (!bfs()) 
			cout << "  No Solution Possible" ;
		cout << endl;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值