其实,,,不管二维三维的这类问题,本质都是一个置换群的对换问题
一置换中的一个长度为k的循环,至少需要k-1次对换才能恢复
对换有个性质就是,一个对换不管变奇偶性都是相同的
我们来看这道题,,其实移动一次0的,,就相当于一个对换,,
我们先将这个三维n数码化为置换,找出有w个循环,那么就说明至少需要对换n*n*n-w次,
再看0到最终位置最小步数x
如果x和n*n*n-x同奇偶性,就说明2个置换能通过对换互相转换,,,恩
#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<queue>
#include<string.h>
#include<string>
#include<cstring>
#include<vector>
#include<time.h>
#include<stdlib.h>
using namespace std;
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define FIN freopen("input.txt","r",stdin)
#define mem(x,y) memset(x,y,sizeof(x))
typedef unsigned long long ULL;
typedef long long LL;
#define fuck(x) cout<<x<<endl;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<pair<int,int>,int> PIII;
typedef pair<int,int> PII;
const double eps=1e-5;
const int MX=1e6+5;
const int P=9973;
int n,w[MX];
bool vis[MX];
namespace IO
{
const int MX = 4e7;
char buf[MX];
int c, sz;
void begin()
{
c = 0;
sz = fread(buf, 1, MX, stdin);
}
inline bool read(int &t)
{
while(c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;
if(c >= sz) return false;
bool flag = 0;
if(buf[c] == '-') flag = 1, c++;
for(t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++) t = t * 10 + buf[c] - '0';
if(flag) t = -t;
return true;
}
}
int main()
{
IO::begin();
int T;
IO::read(T);
while(T--)
{
IO::read(n);
int pp=0;
for(int z=0; z<n; z++)
for(int y=0; y<n; y++)
for(int x=0; x<n; x++)
{
int t;
IO::read(t);
//cout<<t<<endl;
if(t==0)
{
pp=abs(n-1-x)+abs(n-1-y)+abs(n-1-z);
}
if(x==n-1&&y==n-1&&z==n-1)w[0]=t;
else w[x+1+y*n+z*n*n]=t;
}
// cout<<pp<<endl;
int up=n*n*n,cnt=0;
for(int i=0; i<up; i++)vis[i]=0;
//for(int i=0; i<up; i++)cout<<w[i]<<" ";cout<<endl;
for(int i=0; i<up; i++)
if(vis[i]==0)
{
cnt++;
int now=w[i];
vis[i]=1;
while(now!=i)
{
vis[now]=1;
now=w[now];
}
}
//cout<<cnt<<endl;
if((pp+n-cnt)&1)puts("Puzzle is unsolvable.");
else puts("Puzzle can be solved.");
}
return 0;
}