康托展开

Description

魔板由8个大小相同方块组成,分别用涂上不同颜色,用1到8的数字表示。

其初始状态是

1 2 3 4

8 7 6 5

对魔板可进行三种基本操作:

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

用上述三种基本操作,可将任一种状态装换成另一种状态。
Input

输入包括多个要求解的魔板,每个魔板用三行描述。

第一行步数N,表示最多容许的步数。

第二、第三行表示目标状态,按照魔板的形状,颜色用18的表示。

当N等于-1的时候,表示输入结束。
Output

对于每一个要求解的魔板,输出一行。

首先是一个整数M,表示你找到解答所需要的步数。接着若干个空格之后,从第一步开始按顺序给出M步操作(每一步是ABC),相邻两个操作之间没有任何空格。

注意:如果不能达到,则M输出-1即可。
Sample Input
4
5 8 7 6
4 1 2 3
3
8 7 6 5
1 2 3 4
-1
Sample Output

2  AB
1  A
#include <iostream>
#include <string>
#include <queue>
#include <cstring>

using std::string;
using std::queue;

struct node
{
    int fir;
    int sec;
    int lev;
    string str;
    node(int f, int s, int l, string st)
    {
        fir = f;
        sec = s;
        lev = l;
        str = st;
    }
};

int arr[100000];
int fact[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};

int cantor(int a, int b)   
{  
    int temp[8];
    int cnt;      
    for (int i = 7; i >= 0; i--)
    {
        if (i >= 4)
        {
            temp[i] = b % 10;
            b /= 10;
        }
        else
        {
            temp[i] = a % 10;
            a /= 10;
        }
    }
    int t = 0;
    for (int i = 0; i < 7; i++)
    {
        cnt = 0;
        for (int j = i + 1; j < 8; j++)       
            if (temp[i] > temp[j])
                cnt++; 
        t += fact[8 - i - 1] * cnt;
    }     
    return t; 
} 

int main()
{
    int n;
    while (std::cin >> n && n != -1)
    {
        memset(arr, 0, sizeof(arr));
        int temp, fir, sec, sum;
        sum = 0;
        for (int i = 0; i < 8; i++)
        {
            if (i == 4)
            {
                fir = sum;
                sum = 0;
            }
            std::cin >> temp;
            sum = sum * 10 + temp;
        }
        sec = sum;
        node a = node(8765, 1234, 1, "A");
        node b = node(4123, 5876, 1, "B");
        node c = node(1724, 8635, 1, "C");
        queue<node> que;
        que.push(a);
        que.push(b);
        que.push(c);
        int tmp = cantor(1234, 8765);
        arr[tmp] = 1;
        bool jud = false;
        if (fir == 1234 && sec == 8765)
        {
            std::cout << "0 \n";
            continue;
        }
        for (int i = 0; i < n; i++)
        {
            while ((!que.empty()) && que.front().lev == i + 1)
            {
                int t1 = que.front().fir;
                int t2 = que.front().sec;
                bool boo = false;
                //don't equal
                if (t1 == fir && t2 == sec)
                {
                    jud = true;
                    break;
                }
                tmp = cantor(t1, t2);
                if (arr[tmp] == 1)
                    boo = true;
                //don't repeat
                if (!boo)
                {
                    arr[tmp] = 1;
                    string s1 = que.front().str;
                    //A op
                    if (s1[s1.size() - 1] != 'A')
                    {
                        node tnode = node(t2, t1, i + 2, que.front().str + "A");
                        que.push(tnode);
                    }
                    //B op
                    string s2;
                    if (s2.size() >= 3)
                        s2 = s1[s1.size() - 3] + s1[s1.size() - 2] + s1[s1.size() - 1];
                    if (s2 != "BBB")
                    {
                        int t3, t4;
                        t3 = (t1 % 10) * 1000 + (t1 / 10);
                        t4 = (t2 % 10) * 1000 + (t2 / 10);
                        node tnode1 = node(t3, t4, i + 2, que.front().str + "B");
                        que.push(tnode1);
                    }
                    //C op
                    if (s2 != "CCC")
                    {
                        int t5, t6;
                        t5 = t1 / 1000 * 1000 + t1 % 10 + (t1 / 100) % 10 * 10 + (t2 / 100) % 10 * 100;
                        t6 = t2 / 1000 * 1000 + t2 % 10 + (t1 / 10) % 10 * 10 + (t2 / 10) % 10 * 100;
                        node tnode2 = node(t5, t6, i + 2, que.front().str + "C");
                        que.push(tnode2);
                    }
                }
                que.pop();
            }
            if (jud)
                break;
        }
        if (jud)
        {
            std::cout << que.front().lev << " " << que.front().str << std::endl;
        }
        else
        {
            std::cout << -1 << std::endl;
        }
    }
    return 0;
}                                 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值