zoukankan      html  css  js  c++  java
  • SSLZYC 1692 魔板

    题目大意:
    对于一个2*4的魔板,你有三种操作:
    A 交换上下两行
    B 将最右边的一列插入最左边
    C 魔板中央四格作顺时针旋转

    已知

    1234
    8765

    为魔板复原的样子,现在给出一个魔板,要求输出复原的最少步数以及依次进行的操作。


    思路
    这道题我听地真的很懵。。。
    正解是BFS+HASH,从复原的样子开始搜索,把三种变化方法都搜一遍,直到成为了输入的样子(此时的方案绝对是最优方案),然后递归输出。


    代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int k=40319;
    int c[4][9],sum,x,father[k],ha[k],way[k],head,state[k][9],tail;
    char a[k][9],b[k];
    
    void csh()  //初始化
    {
        c[1][1]=8;
        c[1][2]=7;
        c[1][3]=6;
        c[1][4]=5;
        c[1][5]=4;
        c[1][6]=3;
        c[1][7]=2;
        c[1][8]=1;
    
        c[2][1]=4;
        c[2][2]=1;
        c[2][3]=2;
        c[2][4]=3;
        c[2][5]=6;
        c[2][6]=7;
        c[2][7]=8;
        c[2][8]=5;
    
        c[3][1]=1;
        c[3][2]=7;
        c[3][3]=2;
        c[3][4]=4;
        c[3][5]=5;
        c[3][6]=3;
        c[3][7]=6;
        c[3][8]=8;  //所有变化情况
    }
    
    int h(int x)  //哈希函数
    {
        return x%k;  
    }
    
    int locate(int x)  //查找
    {
        int m=0;
        for (int i=1;i<=8;i++)
         m=m*10+state[x][i];  //取出该情况
        int t=h(m);  //求出储存位置
        int i=0;
        while (i<k&&ha[(i+t)%k]!=m&&ha[(i+t)%k]!=0) i++;  //找到一个符合的情况才退出
        if (ha[(i+t)%k]==m) return 1;  //如果查找到(即这种情况已经用更少步的方法得到就返回1)
        else 
        {
            ha[(i+t)%k]=m;  //储存
            return 0;  //返回0
        }
    }
    
    void print(int x)  //递归输出
    {
        if (x==1) return;  //已经无法递归的话就返回
        sum++;  //计数
        if (way[x]==1) b[sum]='A';
        if (way[x]==2) b[sum]='B';
        if (way[x]==3) b[sum]='C';  //判断
        print(father[x]);  //递归
    }
    
    void bfs()
    {
        head=0;
        tail=1;
        father[1]=0;
        way[1]=0;
        for (int i=1;i<=8;i++) state[1][i]=i;  //初始化
        do
        {
            head++;
            for (int i=1;i<=3;i++)  //枚举每种变化
            {
                tail++;
                way[tail]=i;  //记录路径
                father[tail]=head;  //记录父节点
                for (int j=1;j<=8;j++)
                 state[tail][j]=state[head][c[i][j]];  //更改魔板情况
                tail-=locate(tail);  //等于 if (locate(tail)==1) tail--;
                int ok=0;
                for (int i=1;i<=8;i++)  //判断是否已经完成
                 if (state[tail][i]!=state[0][i]) 
                 {
                    ok=1;
                    break;
                 }
                if (ok==0)
                {
                    print(tail);  //输出
                    tail=-1;
                    return;
                }
            }
        }
        while (head<tail);
    }
    
    int main()
    {
        csh();
        int o=0;
        for (int i=1;i<=8;i++)
        {
            scanf("%d",&state[0][i]);
            o=o*10+state[0][i];
        }
        if (o==12345678)  //特殊判断
        {
            printf("0\n\n");
            return 0;
        }
        bfs();
        printf("%d\n",sum);
        for (int i=sum;i>=1;i--)
        {
            putchar(b[i]);  
            if (i%60==0) printf("\n");
        }
        return 0;
    }
    
  • 相关阅读:
    rsync使用
    文件系统、mkdir、touch、nano、cp笔记
    man/ls/clock/date/echo笔记
    Python之路,Day2
    Python之路,Day1
    自动化部署nginx负载均衡及监控短信报警
    NO.11天作业
    Tiny C Compiler简介-wiki
    stm32中使用cubemx配置freertos的信号量大小
    c99的新功能
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313102.html
Copyright © 2011-2022 走看看