Eight -- A*算法

来源:互联网 发布:apache启动失败 编辑:程序博客网 时间:2024/06/10 11:09

http://acm.hdu.edu.cn/showproblem.php?pid=1043


今天又把八数码拿出来写了一遍,记得上次写这题是暑假集训的时候,那时POJ上能过,但是拿到HDU上交就TLE啊,只能说明POJ上,这题的数据太水了, ~~~  这次写主要也是为了学下A*算法吧。 不过我写的A* 在HDU上还是要1000+ms,囧。。 应该是启发函数没有处理好吧。。

算法:A* , BFS, IDA* 


BFS代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#define MAX 363000using namespace std;char ch[30];bool vis[MAX];int d_r[4] = {1,-1,0,0} ;//方向数组 int d_c[4] = {0,0,1,-1} ;bool success ;char path[4] = {'d','u','r','l'} ;//方向数组int fac[11] = {1,1,2,6,24,120,720,5040,40320,362880} ; struct Node{int num[11];//状态 int ka;//该状态对应的KT值 }start,goal;//状态结构体 queue<Node> q ;struct Node2{int pre;//状态(KT值唯一标示)的前一个状态 int way ;//到达该状态的方式 }state[MAX];//求任意一个排列的KT展开 inline int KT(int n,int num[]){int i,j,t,sum=0 ;for(i=1;i<=n;i++){t = 0 ;for(j=i+1;j<=n;j++)if(num[j] < num[i])t++;sum += t *fac[n-i] ;} return sum + 1 ;}inline int recode(char s){if(s == 'x')return 0;elsereturn s - '0' ;}void find(int way,Node now){int num[5][5],i,j,t,pos_r,pos_c;Node a ;for(i=1;i<=3;i++){for(j=1;j<=3;j++){num[i][j] = now.num[(i-1)*3+j];if(num[i][j] == 9){pos_r = i ; pos_c = j ;}}}int new_r = pos_r + d_r[way] ;int new_c = pos_c + d_c[way] ;if(new_r>=1 && new_r<=3 && new_c>=1 && new_c<=3){int temp = num[pos_r][pos_c] ;num[pos_r][pos_c] = num[new_r][new_c] ;num[new_r][new_c] = temp ;t= 1 ;for(i=1;i<=3;i++)for(j=1;j<=3;j++)a.num[t++] = num[i][j] ;a.ka = KT(9,a.num);if(!vis[a.ka]){q.push(a);vis[a.ka] = true; state[a.ka].pre = now.ka ;state[a.ka].way = way ;if(a.ka == goal.ka){success = true ;} }}}void PRINT(int ka)//打印路径 {int pre_ka = state[ka].pre ;if(pre_ka == -1)return ;PRINT(pre_ka);printf("%c",path[state[ka].way]);}int BFS(Node start){int i,j;Node now ;while(!q.empty())q.pop();memset(vis,false ,sizeof(vis));vis[start.ka] = true;q.push(start);success = false ;state[start.ka].pre = -1 ;state[start.ka].way = 0 ;while(!q.empty()){now = q.front(); q.pop();for(i=0;i<4;i++){find(i,now);if(success)break ;}if(success)break;}if(success)PRINT(goal.ka);elseprintf("unsolvable\n");}int main(){int i,j,num,t,pos_x;     //freopen("1in.txt","r",stdin);    //freopen("1out.txt","w",stdout);    for(i=1;i<=9;i++)    {goal.num[i] = i ;}goal.ka = 1 ;   while(gets(ch)!=NULL){t = 1 ;for(i=0;ch[i]!=0;i++){if(ch[i] == ' ')continue ;start.num[t] = recode(ch[i]) ;if(start.num[t] == 0){start.num[t] = 9 ;  }t++ ;}start.ka = KT(9,start.num);BFS(start);//广搜}    return 0;}


A*算法:这题严格来说不是用A*过的,而是用了一个is_ok()函数过的。。


#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<cstdlib>#include<cmath>#define MAX 363000using namespace std;int d_r[4] = {0,0,-1,1} ;//方向数组 int d_c[4] = {1,-1,0,0} ;char path[4] = {'r','l','u','d'} ;//方向数组int fac[11] = {1,1,2,6,24,120,720,5040,40320,362880} ;int d_x[10] = {0,1,1,1,2,2,2,3,3,3} ;int d_y[10] = {0,1,2,3,1,2,3,1,2,3} ;int vis[MAX] ;char ans[MAX] ;struct Node{int num[11];//状态 int ka,space;//该状态对应的KT值int h,g ; friend  bool operator < (const Node & x,const Node & y){return (x.h+x.g) > (y.h+y.g) ;}}start,a,now;//状态结构体 priority_queue<Node> q ;struct Node2{int pre;//状态(KT值唯一标示)的前一个状态 int way ;//到达该状态的方式 }state[MAX];//求任意一个排列的KT展开 inline int KT(int n,int num[]){int i,j,t,sum=0 ;for(i=1;i<=n;i++){t = 0 ;for(j=i+1;j<=n;j++)if(num[j] < num[i])t++;sum += t * fac[n-i] ;} return sum  ;}inline int cal_h(int num[]){int h = 0;for(int i=1;i<=3;i++){for(int j=1;j<=3;j++){int Num = num[(i-1)*3+j] ;h += abs(i - d_x[Num])+abs(j-d_y[Num]) ;}}return h;}inline void swap(int &a, int &b){int temp = a; a = b ; b = temp ;}void PRINT(int ka)//打印路径 {int pre_ka = ka ,t=0;while(state[pre_ka].way != -1){t++; ans[t] = path[state[pre_ka].way] ;pre_ka = state[pre_ka].pre ;}for(int j=t;j>=1;j--){printf("%c",ans[j]);}printf("\n");}void A_star(Node start){int i,j ,temp,pos_r,pos_c,new_r,new_c;start.ka = KT(9,start.num) ;start.g = 0 ;start.h = cal_h(start.num) ;while(!q.empty())q.pop();memset(vis,0,sizeof(vis));//0:未访问,1:已访问结点;  vis[start.ka] = 1 ;q.push(start);state[start.ka].pre = -1 ;state[start.ka].way = -1 ;while(!q.empty()){now = q.top(); q.pop();if(now.ka == 0){PRINT(0) ;return ;}pos_r = (now.space-1)/3 + 1 ;pos_c = (now.space-1)%3 + 1 ;for(i=0;i<4;i++){temp = now.space ;new_r = pos_r + d_r[i] ;new_c = pos_c + d_c[i] ;a = now ;if(new_r<1 || new_r>3 || new_c<1 || new_c>3)continue ;a.space = (new_r-1)*3 + new_c ;swap(a.num[a.space],a.num[temp]) ;a.ka = KT(9,a.num);if(vis[a.ka]==0){a.g = now.g + 1 ;a.h = cal_h(a.num) ;q.push(a);vis[a.ka] = 1;state[a.ka].pre = now.ka ;state[a.ka].way = i ;}}}printf("unsolvable\n");}bool is_ok(int num[]){int sum = 0 ;int num1[11] ,t=1;for(int i=1;i<=9;i++){if(num[i]!=9){num1[t++] = num[i] ;}}for(int i=1;i<=8;i++){for(int j=1;j<i;j++){if(num1[j]>num1[i])sum++;}}if(sum%2==0)return true;elsereturn false ;}int main(){int i,j,num,t,pos_x; char ch[5];    while(cin>>ch[1]>>ch[2]>>ch[3]){for(i=1;i<=3;i++){if(ch[i] == 'x'){start.num[i] = 9 ;start.space = i;}else start.num[i] = ch[i] - '0' ;}for(i=4;i<=9;i++){cin>>ch[0] ;if(ch[0] == 'x'){start.num[i] = 9 ;start.space = i ;}else start.num[i] = ch[0] - '0' ;}if(is_ok(start.num))A_star(start);//广搜else printf("unsolvable\n");}    return 0;}






原创粉丝点击