zoukankan      html  css  js  c++  java
  • 20190801 bfs判重 | 魔板

    洛谷2730魔板

    题目背景

    在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板。这是一张有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 如何判断重复状态??如果每一位枚举的话就太慢了,而且耗空间;
      3 那么可不可以用八进制数来存呢?也不行,这样数组开的太大,会爆空间;
      4 于是我们用康托展开,康托就是某数所在全排列中的排序
      5 bfs少不了queue啦
      6 这里queue存的是上一状态的编号,这里另外使用了一个编号
      7 然后枚举三种操作,判断去重后,记录他的编号,上一状态编号,当前状态步数以及达到当前状态的操作,加入队列即可 
      8 最后达到目标状态递归输出即可 
      9 */
     10 #include<cstdio>
     11 #include<queue>
     12 using namespace std;
     13 struct node
     14 {
     15     int a[3][5];
     16 }start,goal,c[500005];
     17 int goalnum,startnum;
     18 int v[500005];
     19 int jc[9] = {1,1,2,6,24,120,720,5040,423360};
     20 int step[500005],fa[500005],cnt,op[500005];
     21 queue< int>q;
     22 int kangtuo(node x)
     23 {
     24     int res = 0;
     25     int mid[9];
     26     for(int i = 1;i <= 4;i ++)mid[i] = x.a[1][i];
     27     for(int i = 4;i >= 1;i --)mid[9 - i] = x.a[2][i];
     28     for(int i = 1;i <= 8;i ++)
     29     {
     30         int midres = 0;
     31         for(int j = i + 1;j <= 8;j ++)
     32         {
     33             if(mid[j] < mid[i])
     34             {
     35                 midres ++;
     36             }
     37         }
     38         res += midres * jc[8 - i];
     39     }
     40     return res;
     41 }
     42 node change(int k,int u)
     43 {
     44     node res;
     45     if(k == 1)
     46     {
     47         for(int i = 1;i <= 4;i ++)res.a[2][i] = c[u].a[1][i];
     48         for(int i = 1;i <= 4;i ++)res.a[1][i] = c[u].a[2][i];
     49     }
     50     else if(k == 2)
     51     {
     52         res.a[1][1] = c[u].a[1][4];res.a[2][1] = c[u].a[2][4];
     53         for(int i = 2;i <= 4;i ++)res.a[1][i] = c[u].a[1][i - 1];
     54         for(int i = 2;i <= 4;i ++)res.a[2][i] = c[u].a[2][i - 1];
     55     }
     56     else if(k == 3)
     57     {
     58         res = c[u];
     59         res.a[1][2] = c[u].a[2][2];
     60         res.a[1][3] = c[u].a[1][2];
     61         res.a[2][3] = c[u].a[1][3];
     62         res.a[2][2] = c[u].a[2][3];
     63     }
     64     return res;
     65 }
     66 void print(int x)
     67 {
     68     if(x == 1)return ;
     69     print(fa[x]);
     70     if(op[x] == 1)printf("A");
     71     else if(op[x] == 2)printf("B");
     72     else if(op[x] == 3)printf("C");
     73 }
     74 void bfs()
     75 {
     76     while(!q.empty())
     77     {
     78         int u = q.front();
     79         q.pop();
     80         for(int i = 1;i <= 3;i ++)
     81         {
     82             node too = change(i,u);
     83             int midnum = kangtuo(too);
     84             if(!v[midnum])
     85             {
     86                 v[midnum] = 1;
     87                 c[++cnt] = too;//别忘了++cnt啊 
     88                 fa[cnt] = u;
     89                 step[cnt] = step[u] + 1;
     90                 op[cnt] = i;
     91                 if(midnum == goalnum)//这里判断会节省几步 
     92                 {
     93                     printf("%d
    ",step[cnt]);
     94                     print(cnt);
     95                     return ;
     96                 }
     97                 q.push(cnt);
     98             }
     99         }
    100     }
    101 }
    102 int main()
    103 {
    104     for(int i = 1;i <= 4;i ++)start.a[1][i] = i;
    105     for(int i = 4;i >= 1;i --)start.a[2][i] = 9 - i;
    106     for(int i = 1;i <= 4;i ++)scanf("%d",&goal.a[1][i]);
    107     for(int i = 4;i >= 1;i --)scanf("%d",&goal.a[2][i]);
    108     startnum = kangtuo(start);
    109     v[startnum] = 1;
    110     goalnum = kangtuo(goal);
    111     if(startnum == goalnum)
    112     {
    113         printf("0");
    114         return 0;
    115     }
    116     c[++cnt] = start;
    117     step[cnt] = 0;
    118     fa[cnt] = cnt;
    119     op[cnt] = 0;
    120     q.push(1);
    121     bfs();
    122     return 0;
    123 }
  • 相关阅读:
    GreenPlum 锁表以及解除锁定
    Postgresql 解决锁表
    Greenplum 查看连接与锁信息数据字典
    Greenplum 常用数据字典
    Linux 内核参数说明
    Greenplum 如何直连segment节点
    GreenPlum 数据备份与恢复
    unity 获取DontDestroyOnLoad的游戏对象
    scheduleOnce时出错,CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: 0 to 0"
    正比适配,留黑边
  • 原文地址:https://www.cnblogs.com/djfuuxjz/p/11281668.html
Copyright © 2011-2022 走看看