zoukankan      html  css  js  c++  java
  • Problem D: 【宽搜入门】魔板

    Description

    在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板。这是一张有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个字符。

     

    Sample Input

    2 6 8 4 5 7 3 1

    Sample Output

    7

    BCABCCB 

    最终AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    //本题的难点在于 需要记录之前出现的状态 本题采用string来表示
    //题干没有说明未找到的情况,还有输入的序列就是初始序列的情况(经测试,都是BFS()都是返回""
    //题干虽然说每行只输出60个字符,然而没有情况超过60个字符的。。。 
    struct Node{ 
        int M[2][4]; //M保存状态 
        string s; //累计操作 
    }now, nex;
    int des[2][4];
    char op[3] = {'A', 'B', 'C'};
    map<string, bool> mp;
    void getMatrix(char c){
        int i;
        if(c == 'A'){
            for(i=0; i<4; i++) nex.M[0][i] = now.M[1][i];
            for(i=0; i<4; i++) nex.M[1][i] = now.M[0][i];
        }else if(c == 'B'){
            for(i=0; i<2; i++) nex.M[i][0] = now.M[i][3];
            for(i=1; i<4; i++) nex.M[0][i] = now.M[0][i-1];
            for(i=1; i<4; i++) nex.M[1][i] = now.M[1][i-1];
        }else{
            for(i=0; i<2; i++) nex.M[i][0]=now.M[i][0], nex.M[i][3]=now.M[i][3];
            nex.M[0][1]=now.M[1][1], nex.M[0][2]=now.M[0][1];
            nex.M[1][1]=now.M[1][2], nex.M[1][2]=now.M[0][2];
        }
    }
    bool Judge(Node node){
        int i, j;
        for(i=0; i<2; i++){
            for(j=0; j<4; j++) if(node.M[i][j] != des[i][j]) return false;
        }
        return true;
    }
    string getStr(Node node){
        int i;
        string str;
        for(i=0; i<4; i++) str += (node.M[0][i] + '0');
        for(i=0; i<4; i++) str += (node.M[1][i] + '0');
        return str;
    }
    string BFS(){
        string str;
        int i, len;
        now.s = "";
        for(i=0; i<4; i++) now.M[0][i] = i+1;
        now.M[1][0]=8, now.M[1][1]=7, now.M[1][2]=6, now.M[1][3]=5;
        queue<Node> q;
        if(Judge(now)) return now.s;
        q.push(now);
        mp[getStr(now)] = true;
        while(!q.empty()){
            now = q.front();
            q.pop();
            for(i=0; i<3; i++){
                nex.s = now.s + op[i];
                getMatrix(op[i]);
                if(Judge(nex)) return nex.s;
                str = getStr(nex);
                if(!mp[str]){
                    q.push(nex);
                    mp[str] = true;
                }
            }
        }
        return "";
    }
    int main(){
        int i;
        string ans;
        while(cin>>des[0][0]>>des[0][1]>>des[0][2]>>des[0][3]){ //输入第一组 
            cin>>des[1][3]>>des[1][2]>>des[1][1]>>des[1][0]; //输入第二组 
            mp.clear();
            ans = BFS();
            printf("%d
    ", ans.size());
            for(i=0; i<ans.size(); i++) printf("%c", ans[i]);
            printf("
    ");
        }
        return 0;
    }

    总结:这题和上一题其实大同小异,唯一不同的是,这里需要记录出现的状态,否则某些情况会出现死循环从而造成超时。但是,我想吐槽,这题干的描述真的不怎样,尤其是输出!

  • 相关阅读:
    Excel透视表进阶之计算字段、计算项、切片器、页面布局
    Excel透视表进阶之排序、筛选、分组、总计与分类汇总
    Excel透视表基础之字段布局与重命名、更新、数字格式设置、空值与错误值、
    Excel透视表基础之数据源、创建、基本术语、基本操作
    NumPy基础
    Python读写Excel
    逻辑判断
    打印 PRINT
    面向对象
    循环控制
  • 原文地址:https://www.cnblogs.com/heyour/p/12674467.html
Copyright © 2011-2022 走看看