今天看了a*搜尋演算法,聽說牛逼的很,不過關鍵還是在於它的評估函式,估計也不一定每題都能這麼容易想吧
就**來說吧,s,儲存所有所搜到的結點的資訊,包括空格位置,深度及評估值,這裡不給出h是因為h一直在變,b儲存開始結點資訊,visited儲存是否訪問到,接下來方向,答案,heap是為了提速而寫的堆實現的優先佇列,nali是為了區別出是否入隊
整個過程:1,開始結點初始化,入佇列並判斷是否為目標,是就輸出,結束
2,取出隊中優先順序即f最小的結點 ,進行擴充套件
3,各個可擴充套件出來的結點,先求雜湊值,判重,如果重複,並還在佇列中,就保留優先順序較小的那個
4,如果沒重複就入隊
5,判斷是否為目標,是就輸出,結束;否則回到2
**
#include#includeview code#include
#define size 400000
struct
node
s[400000
],b;
int visited[400000],dir[4]=,ans[400000],found;//
0上1下2左3右,
int f[8]=;
int heap[400000],hlength,nali[400000];//
nali中儲存在**,0表示沒在隊裡,1表示在佇列裡
char end[10]=;
void down(int p)//
刪除後向下調整
}heap[p]=a;//
還原原來的點
}int
min()
void up(int p)//
插入後向上調整
heap[p]=a;//
還原原來的點
} void insert(inta)
int hx(char str)//
計算h(x)函式值,計算當前狀態下還未達到正確位置的個數
intget(char str) //
計算全排列雜湊值
return
ret;
} void print(int x)//
若發現可完成,則利用父節點逐個輸出
while (top!=0
)
top--;
}printf("\n
");} void
abfs()
for(i=0;i<4;i++)
//當出現了還在佇列中未出列的,保留f較小的那個
continue
; }
else
if(visited[hash]==0
)
if(strcmp(s[hash].str,end)==0
)
} } int
astar()
}int
main()
else a[j++]=a[i];
}a[j]='\0'
; strcpy(b.str,a);
b.k=m;
found=0;//
標誌變數初始化
//printf("m=%d %s\n",b.k,b.str);
astar();
if(found==0
) printf(
"unsolvable\n");
}//system("pause");
return0;
}
poj 1077 八數碼難題
終於自己ac了這道八數碼難題,用的方法是最最普通的單項bfs hash,這裡主要的難點在於如何儲存狀態,其實,在八數碼裡所有的狀態共有9!種 362880種,所以在每個轉台節點,我需要乙個char state 3 3 來記錄當前棋盤的狀態,用乙個int x,y來記錄當前x的位置,用char oper...
POJ1077 經典的八數碼問題
很經典的八數碼問題,可以用單向廣度優先搜尋 雙向廣度優先搜尋 a 演算法 ida演算法解。用了雙向廣度優先搜尋和a 演算法解,在用a 演算法時,糾結了好幾天,後來在網上看了乙份部落格才發現自己錯在哪。之後解出來了。雖然做這題時很糾結,不過收穫真的很大,痛而快樂著 下面貼出用雙向廣度優先搜尋和a 演算...
poj 1077 Eight A 解八數碼問題
題意 經典的八數碼問題。分析 搜尋演算法的區別是如何重排open表,關鍵是如何編碼狀態和定義狀態的值。對搜尋過程中任意狀態s,a 演算法以g s h s 重排open表,也就是說g s h s 是排列open中狀態的依據,其中g s 是初始狀態到s的消耗,h s 是s到目標狀態的估計。我重排open...