http://acm.hdu.edu.cn/showproblem.php?pid=1043
一个事关人生完不完整得题目,自然就要反复多写几遍才能体会其中的精华咯,哈哈。今天又看到了一个用单广的写法,于是乎觉得很好,就自己又写了一遍,没想到109ms。。 Orz。。 连自己都不敢相信哈!! 神马A*、IDA*,都是浮云啊。
这里简单说思路吧: 从终点开始,预处理出终点能到达的状态(这里终点能达到的状态一定是能达到终点的状态),采用逆向搜索的方法,记录下每种状态达到终点状态的下一个KT值和达到方式,这样在任意读入的一个状态下,只要先判断是否能达,若能达,按照pre数组打出每个方式即可。 没牛的一种思路。。
代码:
/* HDU 1043 Eight Tips:单广搜 Runtime : 109ms */ #include<stdio.h> #include<string.h> #include<queue> #define MAX 362900 using namespace std; struct Node{ char maze[4][4] ; int sx,sy ; }sta[MAX]; queue<Node> q; int pre[MAX]; char way[MAX]; bool vis[MAX]; int fac[9] = {1,1,2,6,24,120,720,5040,40320} ; int dir_x[4] = {0,0,1,-1} ; int dir_y[4] = {1,-1,0,0} ; char dir_w[4] = {'l','r','u','d'} ; // !!!这里的方向和上面的方向数组时相反的; //求一个排列的KT int get_cat(Node a){ int num[10],index=0; for(int i=1;i<=3;i++){ for(int j=1;j<=3;j++){ if(a.maze[i][j] == 'x'){ num[index++] = 9 ; } else num[index++] = a.maze[i][j] - '0' ; } } int res = 0 ; for(int i=0;i<9;i++){ int t= 0 ; for(int j=i+1;j<9;j++){ if(num[i] > num[j]) t++; } res = res + fac[8-i]*t ; } return res ; } //逆向建立可达状态的路径。 void bfs(){ Node a; int num = 1 ,cat; for(int i=1;i<=3;i++){ for(int j=1;j<=3;j++){ if(i==3 && j==3){ a.maze[i][j] = 'x' ;a.sx = i; a.sy = j ; } else {a.maze[i][j] = num + '0' ; num++ ;} } } while(!q.empty()) q.pop(); q.push(a) ; memset(pre,-1,sizeof(pre)); memset(vis,false,sizeof(vis)); cat = get_cat(a); vis[cat] = true ; pre[cat] = -2 ; while(!q.empty()){ Node now = q.front(); q.pop(); int s_x = now.sx ,s_y = now.sy ; for(int i=0;i<4;i++){ Node next = now; int n_x = s_x + dir_x[i] ; int n_y = s_y + dir_y[i] ; if(n_x<1 || n_x>3 || n_y<1 || n_y>3) continue ; char temp = next.maze[s_x][s_y] ; next.maze[s_x][s_y] = next.maze[n_x][n_y] ; next.maze[n_x][n_y] = temp ; next.sx = n_x ;next.sy = n_y ; cat = get_cat(next) ; if(vis[cat]){ continue ; } else{ pre[cat] = get_cat(now) ; way[cat] = dir_w[i] ; q.push(next) ; vis[cat] = true ; } } } } int main() { Node start ; char ss[3] ; bfs(); while(scanf("%s",ss)!=EOF){ start.maze[1][1] = ss[0] ; if(ss[0] == 'x'){ start.sx = 1 ; start.sy = 1 ; } scanf("%s",ss); start.maze[1][2] = ss[0] ; if(ss[0] == 'x'){ start.sx = 1 ; start.sy = 2 ; } scanf("%s",ss); start.maze[1][3] = ss[0] ; if(ss[0] == 'x'){ start.sx = 1 ; start.sy = 3 ; } for(int i=2;i<=3;i++){ for(int j=1;j<=3;j++){ scanf("%s",ss); start.maze[i][j] = ss[0] ; if(ss[0] == 'x'){ start.sx = i ;start.sy = j ; } } } int cat = get_cat(start) ; if(pre[cat] == -1){ printf("unsolvable\n"); } else if(pre[cat] == -2){ printf("\n"); } else{ int now_c ,pre_c ; pre_c = cat ; now_c; while(pre[pre_c]!=-2){ //打印路径即可。 printf("%c",way[pre_c]); pre_c = pre[pre_c] ; } printf("\n"); } } return 0; }