POJ1077 八數碼問題

題目鏈接:http://poj.org/problem?id=1077

經典的八數碼問題,用單向BFS,雙向BFS,A*均可解決!

難點在於狀態壓縮,用9代表x,那麼這個矩形的數字擺放狀態共有9!種。9!並不大,可以開一個數組標記狀態,那麼如何將一個數字擺放狀態轉換爲一個整型的十進制數變成了解決問題的關鍵!

參考康託展開:http://blog.csdn.net/morgan_xww/article/details/6275460

解決了狀態表示問題,下面的編碼就簡單了。


#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define MAX 362890
typedef struct node
{
        int v;
        int x,y;        
}node;
node queue[MAX*10];
int flag[MAX];   //狀態標記數組,並記錄上一個狀態裝換成當前狀態所移動的方向,1-u ,2-d,3-l,4-r;-1代表沒訪問過
int map[10],m;
int d[]={1,1,2,6,24,120,720,5040,40320};
char cc[]="udlr";
int count()  //康託展開
{
    int i,j;
    int sum=0;
    for (i=0;i<9;i++)
    {
        //printf("%d ",map[i]);
        int tot=0;
        for (j=i+1;j<9;j++)
        {
            if (map[i]>map[j])
               tot++;
        }
        sum+=tot*d[8-i];        
    }
    //printf("\n");
    return sum;
}
void swap(int x,int y)
{
     int temp=map[x];
     map[x]=map[y];
     map[y]=temp;
}
void incount(int sum)  //康託展開逆運算
{
     int i,j,t,vs[10]={0};
     for (i=0;i<9;i++)
     {
         t=sum/d[8-i];
         for (j=1;j<=9;j++)
         {
             if (!vs[j])
             {
                if (t==0)
                   break;           
                else
                   t--; 
             }   
         }
         map[i]=j;
         vs[j]=1;
         sum=sum%d[8-i];    
     }    
}
void bfs()
{
     int qs,qe;
     qs=qe=0;
     queue[0].x=-1;
     int tot=count();
     queue[0].y=m;
     queue[qe++].v=tot;
     flag[tot]=0;
     while (qs<qe)
     {
           node temp=queue[qs++];
           incount(temp.v);
           //printf("%d %d %d\n",temp.x,temp.y,temp.v);
           ///system("pause");
           if (temp.v==0)
              break;
           if (temp.y-3>=0)
           {
              swap(temp.y,temp.y-3);
              tot=count();
              //printf("%d\n",tot);
              if (flag[tot]==-1)
              {
                 queue[qe].v=tot;
                 queue[qe].x=qs-1;
                 queue[qe++].y=temp.y-3;
                 flag[tot]=1;                
              }
              swap(temp.y,temp.y-3);
           }
           if (temp.y+3<9)
           {
              swap(temp.y,temp.y+3);
              tot=count();
              //printf("%d\n",tot);
              if (flag[tot]==-1)
              {
                 queue[qe].v=tot;
                 queue[qe].x=qs-1;
                 queue[qe++].y=temp.y+3;
                 flag[tot]=2;                
              }
              swap(temp.y,temp.y+3);
              //system("pause");
           }
           if (temp.y%3!=0)
           {
              swap(temp.y,temp.y-1);
              tot=count();
              //printf("%d\n",tot);
              if (flag[tot]==-1)
              {
                 queue[qe].v=tot;
                 queue[qe].x=qs-1;
                 queue[qe++].y=temp.y-1;
                 flag[tot]=3;                
              }
              swap(temp.y,temp.y-1);
           }
           if (temp.y%3!=2)
           {
              swap(temp.y,temp.y+1);
              tot=count();
              //printf("%d\n",tot);
              if (flag[tot]==-1)
              {
                 queue[qe].v=tot;
                 queue[qe].x=qs-1;
                 queue[qe++].y=temp.y+1;
                 flag[tot]=4;                
              }
              swap(temp.y,temp.y+1);
           }
           //printf("%d\n",qe);
           //printf("\n");
           //count();
           //printf("\n");
     }   
     if (flag[0]==-1)
     {
        printf("unsolvable\n");                
     }  
     else
     {
        int x=qs-1,top=0;
        //queue[top++].v=flag[queue[x].v];
        while (queue[x].x!=-1)
        {
              queue[top++].y=flag[queue[x].v];
              x=queue[x].x;
        }     
        for (int i=top-1;i>=0;i--)
        {
            //printf("%d\n",queue[i].v-1);
            printf("%c",cc[queue[i].y-1]);
        }
        printf("\n");
     }
}
int main()
{
    char s[20];
    while (gets(s))
    {
          int i,j=0,n;
          n=strlen(s);
          memset(flag,-1,sizeof(flag));
          for (i=0;i<n;i++)
          {
              if (s[i]>='0'&&s[i]<='9')
              {
                 map[j++]=s[i]-'0';                         
              }    
              else if (s[i]>='a'&&s[i]<='z')
              {
                 map[j++]=9;
                 m=j-1;       
              }
          }
          /*for (i=0;i<9;i++)
          {
              printf("%d ",map[i]);
          } 
          printf("\n");*/
          bfs();
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章