八數碼問題之盲目式搜索法(雙向搜索法)

本文來自:http://kapinter.spaces.live.com/blog/cns!142AD4209363D971!665.entry

 

題目描述:
  
八數碼問題 之 盲目式搜索法(雙向搜索法)
題目:http://acm.pku.edu.cn/JudgeOnline/problem?id=1077
   
//實質也是寬度優先搜索法 
//但時空都是減少了一個數量級~~ (真正用到的)
 

 

程序部分:
  
//盲目式搜索法--雙向搜索法 
//實質也是寬度優先搜索法 
//但時空都是減少了一個數量級~~ 
  
#include <stdio.h>  
#include <string.h>  
  
typedef struct node {  
       long map; //存儲一個棋盤狀態  
       long father; //倒着找可以得到答案  
       char c; //記錄算符  
} node;  
 
node queue[2][362880 + 1];  
long tail[2], head[2];  
long ans[2]; //存放結合節點 
//-1表示還沒出現 
//否則爲狀態在隊列中的位置 
long hash[2][362880 + 1];  
  
int main()  
{  
       long ReadIn();  
       int NoAnswer(long);  
       void Solve();  
       void OutPut();  
  
       long map = ReadIn();  
       if (NoAnswer(map)) {  
              puts("unsolvable");  
              return 0;  
       }  
 
       queue[0][0].map = map; 
       queue[1][0].map = 123456780; 
       queue[0][0].father = -1; 
       queue[1][0].father = -1; 
       tail[0] = tail[1] = 0; 
       head[0] = head[1] = 0; 
       for (long i=0; i<362880+1; i++) { 
              hash[0][i] = hash[1][i] = -1; 
       } 
 
       Solve();  
       OutPut(); 
       //printf("head[0]==%d head[1]==%d/n", head[0], head[1]); 
  
       return 0;  
}  
  
long ReadIn()  
{  
       long i, t = 0;  
       char s[20];  
  
       for (i=0; i<9; i++) {  
              scanf("%s", s);  
              if (s[0]=='0' || s[0]=='x') {  
                     t = t * 10;  
              }  
              else {  
                     t = t * 10 + s[0] - '0';  
              }  
       }  
  
       return t;  
}  
  
int NoAnswer(long n)  
{  
       long i, j, map[9];  
       long DeCompress(long *, long); 
  
       DeCompress(map, n); 
       long t = 0; 
       for (i=0; i<9; i++) {  
              if (map[i] == 0) continue;  
              for (j=i+1; j<9; j++) {  
                     if (map[j] == 0) continue;  
                     if (map[i] > map[j]) { t++; }  
              }  
       }  
  
       return (t % 2);  
}  
  
void Solve()  
{  
       long map[9]; 
       long DeCompress(long *, long); 
       void Expand(long, node); 
       long Hash(long *); 
 
       DeCompress(map, queue[0][0].map);  
       hash[0][Hash(map)] = 0; 
       DeCompress(map, queue[1][0].map); 
       hash[1][Hash(map)] = 0; 
 
       /* 一定是有解的,所以才這樣寫 */ 
       node e;  
       long i = 0, j; 
 
       while (1) { 
              i = 1 - i; 
              j = 1 - i; 
              e = queue[i][tail[i]++]; 
              DeCompress(map, e.map); 
              if ((ans[j] = hash[j][Hash(map)]) != -1) { 
                     ans[i] = tail[i] - 1; 
                     return; 
              } 
              Expand(i, e); 
       } 
} 
 
long DeCompress(long *map, long n) 
{ 
       long space; 
 
       for (int i=8; i>=0; i--) {  
              map[i] = n % 10;  
              n /= 10;  
              if (map[i] == 0) { space = i; } 
       }  
 
       return space; 
} 
 
void Expand(long sign, node e) 
{ 
       //long DeCompress(long *, long); 
       void swap(long &, long &); 
       long Hash(long *); 
       long Compress(long *); 
 
       long map[9], temp; 
       long space = DeCompress(map, e.map); 
 
       if (space >= 3) { //can up  
              swap(map[space - 3], map[space]);  
              if (hash[sign][temp = Hash(map)] == -1) {  
                     queue[sign][++head[sign]].map = Compress(map);  
                     queue[sign][head[sign]].father = tail[sign] - 1;  
                     queue[sign][head[sign]].c = 'u';  
                     hash[sign][temp] = head[sign]; 
              }  
              swap(map[space - 3], map[space]);  
       }  
       if (space <= 5) { //can down  
              swap(map[space + 3], map[space]);  
              if (hash[sign][temp = Hash(map)] == -1) {  
                     queue[sign][++head[sign]].map = Compress(map);  
                     queue[sign][head[sign]].father = tail[sign] - 1;  
                     queue[sign][head[sign]].c = 'd';  
                     hash[sign][temp] = head[sign]; 
              }  
              swap(map[space + 3], map[space]);  
       }  
       if (space % 3 != 0) { //can left  
              swap(map[space - 1], map[space]);  
              if (hash[sign][temp = Hash(map)] == -1) {  
                     queue[sign][++head[sign]].map = Compress(map);  
                     queue[sign][head[sign]].father = tail[sign] - 1;  
                     queue[sign][head[sign]].c = 'l';  
                     hash[sign][temp] = head[sign]; 
              }  
              swap(map[space - 1], map[space]);  
       }  
       if (space % 3 != 2) { //can right  
              swap(map[space + 1], map[space]);  
              if (hash[sign][temp = Hash(map)] == -1) {  
                     queue[sign][++head[sign]].map = Compress(map);  
                     queue[sign][head[sign]].father = tail[sign] - 1;  
                     queue[sign][head[sign]].c = 'r';  
                     hash[sign][temp] = head[sign]; 
              }  
              swap(map[space + 1], map[space]);  
       }  
}  
  
void swap(long &x, long &y)  
{  
       x ^= y;  
       y ^= x;  
       x ^= y;  
}  
  
long Compress(long *map)  
{  
       long t = 0, i;  
  
       for (i=0; i<9; i++) {  
              t = t * 10 + map[i];  
       }  
  
       return t;  
}  
 
long Hash(long *map)  
{  
       static long formula[9] =   
       { 1, 1, 2, 6, 24, 120, 720, 5040, 40320 };  
 
       long temp[9];  
       for (long i=0; i<9; i++) {  
              temp[i] = map[i];  
       }  
  
       long t = 0;  
       for (i=0; i<9; i++) {  
              t += temp[i] * formula[8 - i];  
              for (long j=i+1; j<9; j++) {  
                     if (temp[j] > temp[i]) temp[j]--;  
              }  
       }  
  
       return t;  
}  
  
void OutPut()  
{  
       char s[200]; 
       long tail, head; 
 
       char opposite[256]; 
       opposite['u'] = 'd'; 
       opposite['d'] = 'u'; 
       opposite['l'] = 'r'; 
       opposite['r'] = 'l'; 
 
       head = 100; 
       tail = 100; 
       while (queue[0][ans[0]].father != -1) { 
              s[--head] = queue[0][ans[0]].c; 
              ans[0] = queue[0][ans[0]].father; 
       } 
       while (queue[1][ans[1]].father != -1) { 
              s[tail++] = opposite[queue[1][ans[1]].c]; 
              ans[1] = queue[1][ans[1]].father; 
       } 
       s[tail] = 0; 
 
       puts(&s[head]); 
}

運算結果:
  
2  3  4  1  5  x  7  6  8
ullddrurdllurrdlurd
Press any key to continue

 

發佈了15 篇原創文章 · 獲贊 14 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章