zoukankan      html  css  js  c++  java
  • 蓝桥杯,历届试题,九宫重排

      这题是寒假快要结束的时候做的(已经开学一周啦),因为自己写的代码有超时,百度后看了康托展开,然后优化成功,花了比较长的时间。题目如下:

    问题描述
      如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

      我们把第一个图的局面记为:12345678.
      把第二个图的局面记为:123.46758
      显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
      本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
    输入格式
      输入第一行包含九宫的初态,第二行包含九宫的终态。
    输出格式
      输出最少的步数,如果不存在方案,则输出-1。
    样例输入
    12345678.
    123.46758
    样例输出
    3
    样例输入
    13524678.
    46758123.
    样例输出
    22
    ---------分割线---------
      此题因为是找最短路径,所以用bfs,不懂康拓展开的可以百度一下,我的代码用到的康拓展开就是把所有的排列情况做了一个折叠,折叠成了一个数,例如.12345678折叠成了0,87654321.折叠成了9!-1(总的排列情况有9!种),这样就可以开一个40万的数组记录当前情况是否已经出现过,即判重,用康拓展开后,我的程序就通过测评了,具体见代码吧。
     1 #include<stdio.h>
     2 typedef struct Point
     3 {
     4     int now[9];
     5     int x;
     6     int step;
     7 }point;
     8 point init,goal;
     9 point T[400000];
    10 int vis[400000];
    11 int E[9]={1,1,2,6,24,120,720,5040,40320};
    12 int move[4][2] ={-1,0,1,0,0,-1,0,1};
    13 int start=0,end=0;
    14 void add(point p)//此函数和下一个函数都是队列操作
    15 {
    16     T[end]=p;
    17     end++;
    18 }
    19 void del()
    20 {
    21     start++;
    22 }
    23 int cantor(int *A)//康拓展开
    24 {
    25     int i,j,s=0,n;
    26     for(i=0;i<9;i++)
    27     {
    28         n=0;
    29         for(j=i+1;j<9;j++)
    30             if(A[i]>A[j])    
    31                 n++;
    32         s+=n*E[8-i];
    33     }
    34     return s;
    35 }
    36 void bfs()
    37 {
    38     int t,g=cantor(goal.now);
    39     point p;
    40     p=init;
    41     add(p);
    42     vis[cantor(init.now)]=1;
    43     while(end-start>0)
    44     {
    45         p=T[start];
    46         if(cantor(p.now)==g)
    47         {
    48             printf("%d",p.step);
    49             return;
    50         }
    51         int i,x,y,x0,y0;
    52         x=p.x/3,y=p.x%3;
    53         for(i=0;i<4;i++)
    54         {
    55             x0=x+move[i][0];
    56             y0=y+move[i][1];
    57             if (x0<0||x0>2||y0<0||y0>2)
    58                 continue;
    59             point q=p;
    60             q.x=x0*3+y0;
    61             q.step++;
    62             q.now[p.x]=q.now[q.x];
    63             q.now[q.x]=0;
    64             t=cantor(q.now);
    65             if(!vis[t])
    66             {
    67                 vis[t]=1;
    68                 add(q);
    69             }
    70         }
    71         del();
    72     }
    73     printf("-1");
    74 }
    75 int main()
    76 {
    77     int i;
    78     char a[10],b[10];
    79     scanf("%s%s",a,b);
    80     for(i=0;i<9;i++)
    81     {
    82         if(a[i]!='.')
    83             init.now[i]=a[i]-'0';
    84         else
    85         {
    86             init.now[i]=0;
    87             init.x=i;
    88         }
    89         if(b[i]!='.')
    90             goal.now[i]=b[i]-'0';
    91         else
    92             goal.now[i]=0;
    93     }
    94     init.step=0;
    95     bfs();
    96     return 0;
    97 }
  • 相关阅读:
    java--Eclipse for mac 代码提示(代码助手,代码联想)快捷键修改
    简单的实现web聊天界面,一对一
    使用ajax方法实现form表单的提交
    select下拉框选择触发事件
    java定时执行任务(一)
    抽象类与接口对比
    SpringMVC拦截器实现登录认证(转发)
    两道关于数字转换的题
    Java之Math类使用小结(转发)
    WordPattern
  • 原文地址:https://www.cnblogs.com/search-the-universe/p/last_month_5.html
Copyright © 2011-2022 走看看