Sicily 1151. 魔板

1151. 魔板

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge

Description

题目和A题相同,在这里我们把数据范围扩大:N可能超过10

请仔细考虑各种情况。

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


评分:M超过N或者给出的操作不正确均不能得分。

Problem Source

ZSUACM Team Member

这题用的广搜,由于题目的测试样例变复杂,深搜会爆(我没试过,感觉上会爆)。但是有个问题,广搜是不好存路径的,其实这个问题很好解决,直接从起点“12345678”广搜到所有终点,用一个string数组来存储路径字符串。

这样带来一个新问题:数组下标最大要开到12345678,这是不可能的,注意到很多下标都被浪费了,比如112、11。其实8! = 40320,我们只需要40320个string的空间即可,具体方法百度康托展开。

这样就变成了一个类似于找到迷宫最短路径的问题,只不过现在迷宫的出口变成了迷宫中的每一个地点,相当于找到到达迷宫中每一个地点的最短路。

#include <algorithm>
#include <iostream>
#include <string>
#include <stdio.h>
#include <queue>
#include <string.h>
#include <vector>
#include <iomanip>
#include <map>
#include <stack>
#include <functional>
#include <list>
#include <cmath>
using namespace std;

struct step {
    string way;
    string num;
    step() {}
    step(string w, string n) {
        way = w;
        num = n;
    }
};

string S[40325];
int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
bool exist[40325];

inline int KT(string s) {
    int i, j, t, sum;
    sum = 0;
    for (int i = 0; i < s.size(); i++) {
        t = 0;
        for (int j = i + 1; j < s.size(); j++) {
            if (s[j] < s[i]) t++;
        }
        sum += t * fac[s.size() - i - 1];
    }
    return sum;
}

void BFS() {

    queue<step> q;
    q.push(step("", "12348765"));
    int pos = KT("12348765");
    exist[pos] = true;
    S[pos] = "";

    while (!q.empty()) {

        step temp = q.front();
        q.pop();

        string tempa, tempb, tempc;
        tempa = tempb = tempc = temp.num;

        // a reverse
        for (int i = 0; i < 4; i++) swap(tempa[i], tempa[i + 4]);

        // b reverse
        char tempChar = tempb[3];
        tempb[3] = tempb[2];
        tempb[2] = tempb[1];
        tempb[1] = tempb[0];
        tempb[0] = tempChar;
        tempChar = tempb[7];
        tempb[7] = tempb[6];
        tempb[6] = tempb[5];
        tempb[5] = tempb[4];
        tempb[4] = tempChar;

        //c reverse
        tempChar = tempc[1];
        tempc[1] = tempc[5];
        tempc[5] = tempc[6];
        tempc[6] = tempc[2];
        tempc[2] = tempChar;

        int pos = KT(tempa);
        if (!exist[pos]) {
            exist[pos] = true;
            S[pos] = temp.way + "A";
            q.push(step(temp.way + "A", tempa));
        }
        pos = KT(tempb);
        if (!exist[pos]) {
            exist[pos] = true;
            S[pos] = temp.way + "B";
            q.push(step(temp.way + "B", tempb));
        }
        pos = KT(tempc);
        if (!exist[pos]) {
            exist[pos] = true;
            S[pos] = temp.way + "C";
            q.push(step(temp.way + "C", tempc));
        }
    }
}

int main() {

    BFS();

    std::ios::sync_with_stdio(false);

    while (1) {
        int n;
        cin >> n;
        if (n == -1) break;
        string s;
        s.resize(8);
        for (int i = 0; i < 8; i++) {
            cin >> s[i];
        }
        int pos = KT(s);
        if (S[pos].size() > n) cout << -1 << endl;
        else {
            cout << S[pos].size() << "  " << S[pos] << endl;
        }
    }

    //getchar();
    //getchar();
    
    return 0;
}              


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值