魔板

题目

在成功地发明了魔方之后,拉比克先生发明了它的二维版本,称作魔板。这是一张有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              B: 4 1 2 3            C:1 7 2 4
 1 2 3 4                 5 8 7 6              8 6 3 5

对于每种可能的状态,这三种基本操作都可以使用。你要编程计算用最少的基本操作完成基本状态到特殊状态的转换,输出基本操作序列。

【输入】

只有一行,包括8个整数,用空格分开(这些整数在范围 1——8 之间),表示目标状态。

【输出Line 1】

:包括一个整数,表示最短操作序列的长度。Line 2:在字典序中最早出现的操作序列,用字符串表示.

【输入样例】

2 6 8 4 5 7 3 1

【 输出样例】

7

BCABCCB

思路

将模板从二维转化为一维变成字符串,例如初始字符串为12345678,然后对字符串进行添加/删改字符操作,达到 A/B/C的状态变化。进行广搜,并加入book数组进行判断此字符串是否出现过,如果出现就不加入队列,从而节约时间。

#include <iostream>
#include <string>
#include <queue>
#include <sstream>
#include <algorithm>
#include <map>
using namespace std;

queue <f> que;
string sss;
string temp1, temp2;
int num;
map<string,int> book;//用于标记book[x]是否出现过
struct f {
    int sum;
    string ss;
    string rout;//路径变化
};
string b(string s)//b变化
{
    string c;
    c = s[3];
    s.insert(0, c);
    c = s[5];
    s.insert(9, c);
    s.erase(4, 1);
    s.erase(4, 1);
    return s;
}
string c(string s)//c变化
{
    string c;
    c = s[6];
    s.insert(1, c);
    c = s[3];
    s.insert(6, c);
    s.erase(3, 1);
    s.erase(7, 1);
    return s;
}
string i2s(long long i, string k)//数字转字符串
{
    stringstream ss;
    ss << i;
    ss >> k;
    return k;
}
int main(void)
{
    int a;
    struct f n, m, u;
    for (int i = 0; i < 8; i++)
    {
        cin >> a;
        num = num * 10 + a;
    }
    sss = i2s(num, sss);//将输入的数字转为字符串
    n.sum = 0;
    n.ss = "12345678";//初始状态
    que.push(n);
    while (!que.empty())
    {
        if (n.ss == sss)
        {//如果符合最终状态就输出来
            cout << n.sum << endl;
            cout << n.rout;
            break;
        }
        temp1 = n.ss, temp2 = n.ss;
        //进行 A 变化
        num = 0;
        for (int i = n.ss.size() - 1; i >= 0; i--)
        {
            num = num * 10 + (n.ss[i] - '0');
        }//字符串转为数字并反转
        m.ss = i2s(num, m.ss);//数字转为字符串
        m.sum = n.sum + 1;//次数加一
        m.rout = n.rout;
        m.rout.insert(m.rout.size(), "A");//进行 A 变化之后,将 A 路径添加到 m 并加入队列
        if (book[m.ss] == 0)//如果m.ss字符串没有出现过就加入队列,标记为1
        {
            que.push(m);
            book[m.ss] = 1;
        }
        //B 变化
        m.ss = b(temp1);
        m.sum = n.sum + 1;
        m.rout = n.rout;
        m.rout.insert(m.rout.size(), "B");
        if (book[m.ss] == 0)
        {
            que.push(m);
            book[m.ss] = 1;
        }
        //V变化
        m.ss = c(temp2);
        m.sum = n.sum + 1;
        m.rout = n.rout;
        m.rout.insert(m.rout.size(), "C");
        if (book[m.ss] == 0)
        {
            que.push(m);
            book[m.ss] = 1;
        }
        que.pop();
        n = que.front();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值