• 洛谷P2730 魔板 Magic Squares


    P2730 魔板 Magic Squares

    题目背景

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

    输入输出样例

    输入样例#1:
    2 6 8 4 5 7 3 1 
    输出样例#1:
    7 
    BCABCCB

    说明

    题目翻译来自NOCOW。

    USACO Training Section 3.2

    /*
        八数码难题那种搜索做多了,这种题也就不叫题了。。
        直接宽搜,记录状态直接map(hash害我无数次我才不要用),字符串直接加加减减拼组起来,我以为会超时呢。
        就是这么暴力的方法,主意一下内存限制,队列不要开得太大,当然循环队列这里用不到。
        在注意一下输出格式,就可以A了。
    */
    #include<iostream>
    #include<cstdio>
    #include<map>
    #include<cstring>
    
    using namespace std;
    map<string,bool>vis;
    struct node{
        int fa,step;
        string s;
        char op;
    }cur,nxt,q[5000000];
    int head=1,tail=0;
    string goal,start="12348765",ans;
    void work(int now){
        if(q[now].fa==-1)return;
        work(q[now].fa);
        //printf("%c",q[now].op);
        ans+=q[now].op;
    }
    int main(){
        //freopen("Cola.txt","r",stdin);
        int x;
        string ch;
        for(int i=1;i<=8;i++){
            scanf("%d",&x);
            ch+=x+'0';
        }
        goal+=ch.substr(0,4);
        for(int i=7;i>=4;i--)goal+=ch[i];
        cur.s=start;cur.fa=-1;cur.step=0;
        vis[cur.s]=1;
        if(cur.s==goal){
            printf("0");
            return 0;
        }
        q[++tail]=cur;
        while(head<=tail){
            cur=q[head];
            string s=cur.s;
            if(cur.s==goal){
                printf("%d
    ",cur.step);
                work(head);
                int start=0,len=ans.length();
                while(start<len){
                    cout<<ans.substr(start,60);
                    start+=60;
                }
                break;
            }
            //操作A
            nxt.s="";
            nxt.s+=s.substr(4,4);nxt.s+=s.substr(0,4);
            nxt.op='A';nxt.step=cur.step+1;nxt.fa=head;
            if(!vis[nxt.s])q[++tail]=nxt,vis[nxt.s]=1;
            if(nxt.s==goal){
                printf("%d
    ",nxt.step);
                work(tail);
                int start=0,len=ans.length();
                while(start<len){
                    cout<<ans.substr(start,60);
                    start+=60;
                }
                break;
            }
            
            //操作B 
            nxt.s="";
            nxt.s+=s[3];nxt.s+=s.substr(0,3);
            nxt.s+=s[7];nxt.s+=s.substr(4,3);
            nxt.op='B';nxt.step=cur.step+1;nxt.fa=head;
            if(!vis[nxt.s])q[++tail]=nxt,vis[nxt.s]=1;
            if(nxt.s==goal){
                printf("%d
    ",nxt.step);
                work(tail);
                int start=0,len=ans.length();
                while(start<len){
                    cout<<ans.substr(start,60);
                    start+=60;
                }
                break;
            }
            
            //操作C 
            nxt.s="";
            nxt.s+=s[0];nxt.s+=s[5];nxt.s+=s[1];nxt.s+=s[3];nxt.s+=s[4];nxt.s+=s[6];nxt.s+=s[2];nxt.s+=s[7];
            nxt.step=cur.step+1;nxt.op='C';nxt.fa=head;
            if(!vis[nxt.s])q[++tail]=nxt,vis[nxt.s]=1;
            if(nxt.s==goal){
                printf("%d
    ",nxt.step);
                work(tail);
                int start=0,len=ans.length();
                while(start<len){
                    cout<<ans.substr(start,60);
                    start+=60;
                }
                break;
            }
            head++;
        }
        /*int sz=sizeof(q)+sizeof(vis);
        cout<<endl<<sz/1048576;*/
    }
  • 相关阅读:
    修改linux命令行提示符颜色
    passwd命令
    用户与用户组
    计划任务
    sed简单用法
    sed命令实现对文件内容的添加
    C#颜色选择器的调用操作
    插入排序算法的学习
    二叉树的学习记录
    判断两个单链表是否相交及相交的第一个节点
  • 原文地址:https://www.cnblogs.com/thmyl/p/7603869.html
Copyright © 2020-2023  润新知