习题7-9(uva-1604)

#include <iostream>
#include <istream>
#include <sstream>
#include <vector>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <numeric>
#include <chrono>
#include <ctime>
#include <cmath>
#include <cctype>
#include <string>
#include <cstdio>
#include <iomanip>


#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <iterator>
using namespace std;
//每3个bite位 为一个格子 0-5表示颜色 7表示空格 
enum Color { White = 0, Red = 2, Blue = 4, Empty = 7 };
//上下左右
const int Dir[4][2] = { {0,-1},{0,1} ,{-1,0},{1,0} };


unordered_set<int> visHead,visTail;
queue<int> head, tail;
char input[10];
int inputX, inputY, inputBase,ans;

/*
颜色值对应的状态
白红蓝(顶部  对面  左右)
0 - 白红蓝   上下变换 3 - 红白蓝   左右变换 5 - 蓝红白
1 - 白蓝红   上下变换 4 - 蓝白红   左右变换 2 - 红蓝白
2 - 红蓝白   上下变换 5 - 蓝红白   左右变换 1 - 白蓝红
3 - 红白蓝   上下变换 0 - 白红蓝   左右变换 4 - 蓝白红
4 - 蓝白红   上下变换 1 - 白蓝红   左右变换 3 - 红白蓝
5 - 蓝红白   上下变换 2 - 红蓝白   左右变换 0 - 白红蓝
*/
//当前状态按方向滚动的结果
int TurnMove(int base, int dir) {
	//上下
	if (dir == 0 || dir == 1) return (base + 3) % 6;
	//左右
	return (base & 1) ? (base + 1) % 6 : (base - 1 + 6) % 6;
}
//获取下标对应的 一维数组坐标 和常规的相反
int GetIndex(int x, int y) {
	return ((x - 1) + (y - 1) * 3);
}
//获取颜色 
int GetColor(int base ,int index) {
	return (base >> (index * 3)) & 0x07;
}
//设置颜色
void SetColor(int &base,int index,int value) {
	base = (base & (~(0x07 << (index * 3)))) | (value << (index * 3));
}
//找空的位置下标
int GetEmptyIndex(int base) {
	for (int i = 0; i < 9; i++) {
		if (GetColor(base, i) == 0x07) return i;
	}
	return -1;
}
//获得最后的所有状态
void GetLast(int cur,int base) {
	if (ans != -1) return;
	if (cur == 9) { 
		if (base == inputBase) {
			ans = 0;
			return;
		}
		tail.push(base);
		visTail.insert(base);
		return;
	}

	int c = input[cur];
	//两种情况
	SetColor(base, cur, c);GetLast(cur + 1, base);
	//空格不用变
	if (c != 0x07) { SetColor(base, cur, c + 1); GetLast(cur + 1, base); }
}

void DealInput()
{
	while (!head.empty()) head.pop();
	while (!tail.empty()) tail.pop();
	visHead.clear();
	visTail.clear();

	SetColor(inputBase = 0, GetIndex(inputX, inputY), 0x07);
	head.push(inputBase);
	visHead.insert(inputBase);

	for (int i = 0; i < 9; i++) {
		cin >> input[i];
		if (input[i] == 'W') input[i] = White;
		else if (input[i] == 'R') input[i] = Red;
		else if (input[i] == 'B') input[i] = Blue;
		else input[i] = Empty;
	}
	ans = -1;
	GetLast(0,0);
}
//双向广度有限 q - 自己的队列  a - 自己已经遍历的组合  b - 对立方已经遍历的组合
bool DoOnce(queue<int> &q, unordered_set<int> &a, unordered_set<int> &b)
{
	if (q.empty()) return false;

	int len = q.size();
	for (int i = 0; i < len; i++) {
		int base = q.front();
		q.pop();
		int index = GetEmptyIndex(base);
		int x = index % 3 + 1;
		int y = index / 3 + 1;
		//遍历4个方向
		for (int j = 0; j < 4; j++) {
			int nx = x + Dir[j][0];
			int ny = y + Dir[j][1];
			if(nx < 1 || nx > 3 || ny < 1 || ny > 3) continue;
			//获取对应 坐标的 颜色
			int t = base,c = GetColor(t,GetIndex(nx,ny));
			//上下 和 左右 滚动效果一样 就没有做变换
			SetColor(t, GetIndex(x, y), TurnMove(c,j));
			SetColor(t, GetIndex(nx, ny), 0x07);
			//重复的不用了
			if(a.count(t)) continue;
			//已经接头了 说明已经找到
			if (b.count(t)) return true;
			a.insert(t);
			q.push(t);
		}
	}
	return false;
}

void GetResult()
{
	int cnt = 1;
	while (cnt <= 30) {
		//谁的数据小写 就用谁
		if (head.size() < tail.size())
		{
			if (DoOnce(head, visHead, visTail)) break; ++cnt;
		}
		else {
			if (DoOnce(tail, visTail, visHead)) break; ++cnt;
		}
	}
	if (cnt <= 30) ans = cnt;
}
int main()
{
	while (cin >> inputX >> inputY && inputX && inputY) {
		DealInput();
		if(ans == -1) GetResult();
		cout << ans << endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值