#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;
}
01-09
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交