UVALive 4361 Tobo or not Tobo

本文探讨了如何通过预处理所有可能的状态,并计算从初始状态到任意状态所需的最小步数,适用于九宫格状态转换问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
   As it's only 9^9 status at most(in fact, it's not that much),
   We can calculate all the status,
   which can be reached from initial status 123456789 and
   the number of steps not larger than 9, in advance.
*/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <cctype>
#include <queue>
#include <stack>
#include <cmath>
using namespace std;
//STL-Alias
#define UN(c, a) unique(c, a)
#define MS(c, a) memset(c, a, sizeof c)
#define FLC(c, a ,b) fill(c, c + a, b)
#define LOS(c, a, b) lower_bound(c, a, b)
#define UPS(c, a, b) upper_bound(c, a, b)
//Syntax-Alias
#define Rep(c, a, b) for (int c = (a); c < (b); c++)
#define Nre(c, a, b) for (int c = (a); c > (b); c--)
//B-OP
#define LM(x, y) ((x) << (y))
#define RM(x, y) ((x) >> (y))
#define GB(x, y) (RM(x, y) & 1)
#define SB(x, y) (LM(1, y) | x)
#define SBI(x, a, b) ((LM(1, b) - LM(1, a)) | x)
#define CBI(x, a, b) (~(LM(1, b) - LM(1, a)) & x)
//DEBUG
#define FK puts("Fu*k here!")
#define PA(s, c, a, b, p, f){\
	printf(s);\
	Rep(c, a, b) printf(p, (f));\
	puts("");}
//Constant
#define MOD (1000000000LL)
#define MAXN (1 << 16)
//Type-Alias
typedef long long LL;
typedef long double LD;
typedef int AI[MAXN];
typedef double AD[MAXN];
typedef LL ALL[MAXN];
typedef LD ALD[MAXN];


//H[s] as Minimum steps to state s 
map<LL, int> H; 
//Four kinds of rotate
int mr[4][4] = {{0, 1, 4, 3}, {1, 2, 5, 4}, {3, 4, 7, 6}, {4, 5, 8, 7}}; 
//Encode
int EC(int b[3][3])
{
	int s = 0;
	Rep(i, 0, 3) Rep(j, 0, 3)
		s = s * 10 + b[i][j];
	return s;
}
//Decode
void DC(int s, int b[3][3])
{
	Nre(i, 2, -1) Nre(j, 2, -1)
	{
		b[i][j] = s % 10;
		s /= 10;
	}
}
//Rotate function, d indicate direction
int rot(LL s, int *m, int d)
{
	int cp = 0, x = m[cp] / 3, y = m[cp] % 3, b[3][3];
	DC(s, b);
	int t = b[x][y];
	Rep(j, 1, 4)
	{
		int np = (cp + d + 4) % 4, tx = m[np] / 3, ty = m[np] % 3;
		b[x][y] = b[tx][ty];
		cp = np;
		x = tx;
		y = ty;
	}
	b[x][y] = t;
	return EC(b);
}
//Pretreatment 
void H_ini()
{
	H.clear();
	queue<LL> Q;
	LL u = 123456789;
	H[u] = 1;
	Q.push(u);
	while (!Q.empty())
	{
		u = Q.front(); Q.pop();
		if (H[u] > 8) continue;
		Rep(i, 0, 4) Rep(j, -1, 2)
		{
			LL v = rot(u, mr[i], j);
			if (!H[v])
			{
				H[v] = H[u] + 1;
				Q.push(v);
			}
			j++;
		}
	}
}


LL s;


int main()
{
#if 1
	freopen("test.txt", "r", stdin);
#endif
	//Initialize
	int Cas = 1;
	H_ini();
	//Solve
	while (scanf("%lld", &s), s)
	{
		printf("%d. ", Cas++);
		LL p = s / MOD;
		s %= MOD;
		if (H[s] && H[s] - 1 <= p) printf("%d\n", H[s] - 1);
		else puts("-1");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值