UVALive - 5542 Commedia dell' arte 三维n数码问题

其实,,,不管二维三维的这类问题,本质都是一个置换群的对换问题

一置换中的一个长度为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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值