http://acm.hdu.edu.cn/showproblem.php?pid=6171
题意:有一个塔,这个塔一共有6层,第i-1层有i个数字,数字为i-1。
现在给你一个塔,要你恢复成原来的那样,但是你每次只能移动0这个数字,可移动的方向为左上,上,下,右下。
然后问你多少步可以到达
思路:如果简单的dfs的话,那么肯定会超时,那么我们考虑双向dfs,也就是正向反向都跑bfs,然后第一次碰到,肯定是最少的次数
对于bfs的标记,我们可以hash成字符串来进行标记
1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #include <iostream> 5 #include <string> 6 #include <map> 7 using namespace std; 8 9 int dic[4][2]={-1,0,-1,-1,1,0,1,1}; 10 11 struct Node{ 12 int pos[10][10]; 13 bool flag; //1代表s,0代表t 14 int x,y; 15 int step; 16 }s,t; 17 18 string judge(Node x) 19 { 20 string str = ""; 21 for(int i =0;i<6;i++) 22 for(int j = 0;j<=i;j++) 23 str+=x.pos[i][j]+'0'; 24 return str; 25 } 26 27 map<string,int>mp[2]; 28 queue<Node>q; 29 30 31 int dfs() 32 { 33 while(!q.empty()) 34 q.pop(); 35 mp[0].clear(); 36 mp[1].clear(); 37 string tmp = judge(s); 38 mp[1][tmp] = 0; 39 tmp = judge(t); 40 mp[0][tmp] = 0; 41 s.flag = 1,t.flag = 0; 42 s.step = t.step = 0; 43 q.push(s); 44 q.push(t); 45 while(!q.empty()) 46 { 47 Node lo,cy; 48 lo = q.front(); 49 q.pop(); 50 if(mp[!lo.flag].count(judge(lo)) != 0) 51 if(mp[!lo.flag][judge(lo)]+lo.step<=20) 52 return mp[!lo.flag][judge(lo)]+lo.step; 53 54 else 55 continue; 56 if(lo.step>=10) 57 continue; 58 for(int i = 0;i<4;i++) 59 { 60 cy = lo; 61 cy.x = lo.x+dic[i][0]; 62 cy.y = lo.y+dic[i][1]; 63 if(cy.x<0||cy.x>6||cy.y>cy.x||cy.y<0) 64 continue; 65 swap(cy.pos[cy.x][cy.y],cy.pos[lo.x][lo.y]); 66 tmp = judge(cy); 67 if(mp[cy.flag].count(tmp)) 68 continue; 69 mp[cy.flag][tmp] = ++cy.step; 70 q.push(cy); 71 } 72 } 73 return -1; 74 } 75 76 77 78 79 80 int main() 81 { 82 int T; 83 scanf("%d",&T); 84 while(T--) 85 { 86 for(int i = 0;i<6;i++) 87 { 88 for(int j = 0;j<=i;j++) 89 { 90 scanf("%d",&s.pos[i][j]); 91 if(s.pos[i][j]==0) 92 { 93 s.x = i; 94 s.y = j; 95 } 96 t.pos[i][j] = i; 97 } 98 } 99 int ans = dfs(); 100 if(ans==-1) 101 printf("too difficult\n"); 102 else 103 printf("%d\n",ans); 104 } 105 return 0; 106 }