1. 程式人生 > >魔板 Magic Squares(廣搜,狀態轉化)

魔板 Magic Squares(廣搜,狀態轉化)

整數 展開 fine cstring d+ 康拓 空格 來看 reg

題目背景

在成功地發明了魔方之後,魯比克先生發明了它的二維版本,稱作魔板。這是一張有8個大小相同的格子的魔板:

1 2 3 4

8 7 6 5

題目描述

我們知道魔板的每一個方格都有一種顏色。這8種顏色用前8個正整數來表示。可以用顏色的序列來表示一種魔板狀態,規定從魔板的左上角開始,沿順時針方向依次取出整數,構成一個顏色序列。對於上圖的魔板狀態,我們用序列(1,2,3,4,5,6,7,8)來表示。這是基本狀態。

這裏提供三種基本操作,分別用大寫字母“A”,“B”,“C”來表示(可以通過這些操作改變魔板的狀態):

“A”:交換上下兩行;

“B”:將最右邊的一列插入最左邊;

“C”:魔板中央四格作順時針旋轉。

下面是對基本狀態進行操作的示範:

A: 8 7 6 5

1 2 3 4

B: 4 1 2 3

5 8 7 6

C: 1 7 2 4

8 6 3 5

對於每種可能的狀態,這三種基本操作都可以使用。

你要編程計算用最少的基本操作完成基本狀態到目標狀態的轉換,輸出基本操作序列。

輸入輸出格式

輸入格式:

只有一行,包括8個整數,用空格分開(這些整數在範圍 1——8 之間)不換行,表示目標狀態。

輸出格式:

Line 1: 包括一個整數,表示最短操作序列的長度。

Line 2: 在字典序中最早出現的操作序列,用字符串表示,除最後一行外,每行輸出60個字符。

思路:

廣搜應該大家都知道,但是狀態怎麽存?(8^8的數組絕對爆空間)

(大佬:康拓展開)

我不會啊qwq

沒辦法嘍,只能從排列數來看

8!,空間裝得下

那麽我們就該想一下怎麽算位置了

比如說一個狀態

4 1 2 3

8 5 6 7

我們按著行來算,化成一個數字

41238567

在這個數據前有多少個排列呢?

我們一位一位看

首先,看第一位

此時沒有用過且比4小的數有1 2 3 三個

所以就有7!*3個數在他前面

再看第二位

沒有比他小的數,跳過

一位一位地算,就可以知道有多少個比他小的排列

最後+1,就是編號嘍

需要調換的時候編號轉狀態是同理的

廣搜就好嘍

註意:他的數據為順時針給出,我的程序為按行讀入

所以初始狀態1 2 3 4 5 6 7 8

在我這裏的映射為

1 2 3 4

8 7 6 5

代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rii register int i
#define rij register int j
using namespace std;
bool bj[40325];
int n;
struct que{
    int zt,sd,pre,cz;
}q[40325];
int st,jc[10]={0,1,2,6,24,120,720,5040,40320},cnt;
int ans[100005];
int change(int xl)
{
    int mc=1;
    int ls[10]={0,0,0,0,0,0,0,0,0,0};
    int sy[10]={0,0,0,0,0,0,0,0,0,0};
    for(rii=8;i>=1;i--)
    {
        ls[i]=xl%10;
        xl/=10;
    }
    for(rii=1;i<=7;i++)
    {
        int ltt=ls[i];
        for(rij=1;j<=ltt-1;j++)
        {
            if(sy[j]!=1)
            {
                mc+=jc[8-i];
            }
        }
        sy[ltt]=1;
    }
    return mc;
}
void add(int bh,int pre,int cz)
{
    cnt++;
    q[cnt].cz=cz;
    q[cnt].pre=pre;
    q[cnt].zt=bh;
    q[cnt].sd=q[pre].sd+1;
}
void A(int bh,int pre)
{
    bh--;
    int ls[10]={0,0,0,0,0,0,0,0,0,0};
    int sy[10]={0,0,0,0,0,0,0,0,0,0};
    for(rii=1;i<=7;i++)
    {
        int ltt=bh/jc[8-i];
        bh-=ltt*jc[8-i];
        int sl=0;
        for(rij=1;j<=8;j++)
        {
            if(sy[j]!=1)
            {
                sl++;
            }
            if(sl==ltt+1)
            {
                sy[j]=1;
                ls[i]=j;
                break;
            }
        }
    }
    for(rii=1;i<=8;i++)
    {
        if(sy[i]==0)
        {
            ls[8]=i;
            break;
        }
    }
    memset(sy,0,sizeof(sy));
    for(rii=1;i<=4;i++)
    {
        int kkk=ls[i];
        ls[i]=ls[i+4];
        ls[i+4]=kkk;
    }
    int mc=1;
    for(rii=1;i<=7;i++)
    {
        int ltt=ls[i];
        for(rij=1;j<=ltt-1;j++)
        {
            if(sy[j]!=1)
            {
                mc+=jc[8-i];
            }
        }
        sy[ltt]=1;
    }
    if(bj[mc]!=1)
    {
        add(mc,pre,1);
        bj[mc]=1;
    }
}
void B(int bh,int pre)
{
    bh--;
    int ls[10]={0,0,0,0,0,0,0,0,0,0};
    int sy[10]={0,0,0,0,0,0,0,0,0,0};
    for(rii=1;i<=7;i++)
    {
        int ltt=bh/jc[8-i];
        bh-=ltt*jc[8-i];
        int sl=0;
        for(rij=1;j<=8;j++)
        {
            if(sy[j]!=1)
            {
                sl++;
            }
            if(sl==ltt+1)
            {
                sy[j]=1;
                ls[i]=j;
                break;
            }
        }
    }
    for(rii=1;i<=8;i++)
    {
        if(sy[i]==0)
        {
            ls[8]=i;
            break;
        }
    }
    memset(sy,0,sizeof(sy));
    int a1=ls[4];
    int b1=ls[8];
    for(rii=4;i>=2;i--)
    {
        ls[i]=ls[i-1];
        ls[i+4]=ls[i+3];
    }
    ls[1]=a1;
    ls[5]=b1;
    int mc=1;
    for(rii=1;i<=7;i++)
    {
        int ltt=ls[i];
        for(rij=1;j<=ltt-1;j++)
        {
            if(sy[j]!=1)
            {
                mc+=jc[8-i];
            }
        }
        sy[ltt]=1;
    }
    if(bj[mc]!=1)
    {
        add(mc,pre,2);
        bj[mc]=1; 
    }
}
void output(int fi)
{
    int len=q[fi].sd;
    printf("%d\n",len);
    int wz=fi;
    for(rii=len;i>=1;i--)
    {
        ans[i]=q[wz].cz;
        wz=q[wz].pre;
    }
    int cnt=0;
    for(rii=1;i<=len;i++)
    {
        if(ans[i]==1)
        {
            putchar(A);
            continue;
        }
        if(ans[i]==2)
        {
            putchar(B);
            continue;
        }
        else
        { 
            putchar(C);
        }
        cnt++;
        if(cnt==60)
        {
            puts("");
            cnt=0;
        }
    }
}
void C(int bh,int pre)
{
    bh--;
    int ls[10]={0,0,0,0,0,0,0,0,0,0};
    int sy[10]={0,0,0,0,0,0,0,0,0,0};
    for(rii=1;i<=7;i++)
    {
        int ltt=bh/jc[8-i];
        bh-=ltt*jc[8-i];
        int sl=0;
        for(rij=1;j<=8;j++)
        {
            if(sy[j]!=1)
            {
                sl++;
            }
            if(sl==ltt+1)
            {
                sy[j]=1;
                ls[i]=j;
                break;
            }
        }
    }
    for(rii=1;i<=8;i++)
    {
        if(sy[i]==0)
        {
            ls[8]=i;
            break;
        }
    }
    memset(sy,0,sizeof(sy));
    int a2=ls[2],a3=ls[3],b2=ls[6],b3=ls[7];
    ls[3]=a2;
    ls[2]=b2;
    ls[6]=b3;
    ls[7]=a3;    
    int mc=1;
    for(rii=1;i<=7;i++)
    {
        int ltt=ls[i];
        for(rij=1;j<=ltt-1;j++)
        {
            if(sy[j]!=1)
            {
                mc+=jc[8-i];
            }
        }
        sy[ltt]=1;
    }
    if(bj[mc]!=1)
    {
        add(mc,pre,3);
    }
    bj[mc]=1;
}
int main()
{
    scanf("%d",&st);
    for(rii=2;i<=4;i++)
    {
        int ltt;
        st*=10;
        scanf("%d",&ltt);
        st+=ltt;
    }
    st*=10000;
    int sr;
    scanf("%d",&sr);
    st+=sr;
    scanf("%d",&sr);
    st+=sr*10;
    scanf("%d",&sr);
    st+=sr*100;
    scanf("%d",&sr);
    st+=sr*1000;
    int fi=change(st);
    q[1].zt=24;
    bj[24]=1;
    cnt=1;
    for(rii=1;i<=cnt;i++)
    {
        int z=q[i].zt;
        if(z==fi)
        {
            output(i);
            return 0;
        }
        A(z,i);
        B(z,i);
        C(z,i);
    }
}

魔板 Magic Squares(廣搜,狀態轉化)