MX的密码锁 (广搜)

在赢得了友谊赛后, MX获得了无敌变身的技能,他带着技能在寒假去ZKY做了实习工,并在寒假结束之后获得了一大笔财富,MX为了不让这笔钱充公,决定将这笔私房钱藏起来,连MM也不告诉藏在哪,为此MM很是苦恼(有钱不让我花)。有一天MM在工作室偶然发现了一个小箱子,箱子上除了有一个3*3的密码锁外还写着“MX的私房钱”(MDZZ)。密码锁有以下四种操作:

1.使同一列中三个数同时向下移动一格,并使最下面的数字转动到同列第一行

2.使同一列中三个数同时向上移动一格,并使最上面的数字转动到同列最后一行

3.使同一行中三个数同时向右移动一格,并使最右面的数字转动到同行第一列

4.使同一行中三个数同时向左移动一格,并使最左面的数字转动到同行最后一列

由于密码锁潮湿生锈,每对密码锁进行一次操作需要1 min的时间,现在MX快回工作室了,MM需要将密码锁移动成初始状态来打开密码锁,但却不知道是否能赶在MX回来之前,聪明的你可以帮助MM计算最短开锁时间吗? (当开锁时间大于5时,则不能赶在MX回来之前打开,就认为密码锁无解)


如图初始状态为 294753618

目标解锁状态为123456789

输入

第一行一个数字T,表示T组输入数据 T<=10

 

接下来T行,每行包含九个数字,中间无空格隔开,表示密码锁的开始状态

输出

每组数据输出一行,一个数字,表示打开密码锁的最短时间,密码锁无解输出“impossible”

 

(当开锁时间大于5时,则不能赶在MX回来之前打开,就认为密码锁无解)

样例输入
3123456789531496827846953172
样例输出

03impossible

思路:每一层每一列都有两种方向,把这12种方向都列出来,判断步数,超过5步的就不入队列,因为最多搜5层,所以没有标记已经搜过的情况。12种改变的是下标,

例如1 2 3 4 5 6 7 8 9 第一行向左移动,得出的是2 3 1 4 5 6 7 8 9 ,1的下标是—+2,2 ,3 的下标都是-1,所以,next数组代表的是的是这个位置的数的下标的改变值。

#include
#include
#include
#include
using namespace std;
struct node{
int stemp;
char c[10];
}D,d;
queueq;
int main(){
    int t,k,i,j,ans;
    char b[10]={'1','2','3','4','5','6','7','8','9'};
    int next[12][10]={
   {2,-1,-1,0,0,0,0,0,0},
   {1,1,-2,0,0,0,0,0,0},
   {0,0,0,2,-1,-1,0,0,0},
   {0,0,0,1,1,-2,0,0,0},
   {0,0,0,0,0,0,2,-1,-1},
   {0,0,0,0,0,0,1,1,-2},
   {6,0,0,-3,0,0,-3,0,0},
   {3,0,0,3,0,0,-6,0,0},
   {0,6,0,0,-3,0,0,-3,0},
   {0,3,0,0,3,0,0,-6,0},
   {0,0,6,0,0,-3,0,0,-3},
   {0,0,3,0,0,3,0,0,-6}
   };
   scanf("%d",&t);
    while(t--){
   // printf("t=%d\n",t);
    scanf("%s",D.c);
    queueq;
    ans=0;
    while(!q.empty()) q.pop();
    D.stemp=0;
    q.push(D);
  //  printf("R ");
    //  printf("%s %d\n",D.c,D.stemp);


    while(!q.empty()){
        D=q.front();
        q.pop();
     //   printf("C ");
     //  printf("%s %d\n",D.c,D.stemp);
        int f=0;
        for(i=0;i<9;i++)
        {
          if(D.c[i]!=b[i]){
            f=1;
            break;
          }
        }
        if(!f){
            printf("%d\n",D.stemp);
            ans=1;
            break;
        }
        for(k=0;k<12;k++){
    for(i=0;i<9;i++)
        d.c[i+next[k][i]]=D.c[i];
        d.stemp=D.stemp+1;
        if(d.stemp<=5)
        {
            q.push(d);
        //    printf("R ");
        // printf("%s %d\n",d.c,d.stemp);
        }

       }
    }
    if(ans==0)
        printf("impossible\n");
}
}


你可能感兴趣的:(ACM—广搜)