和HDU1043一样的题目,这次用DBFS实现。
感觉写的还是不错的,中间一些细节错误了很多次。
具体见代码。
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <vector> #include <stack> #include <map> #include <iomanip> #define PI acos(-1.0) #define Max 500005 #define inf 1<<28 #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define Rep(i,s,t) for(int i=(s);i<=(t);++i) #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define mp(a,b) make_pair(a,b) using namespace std; struct kdq { string op; char Map[4][4] ; int x ,y ; void show() { Rep(i,0,2) { Rep(j,0,2) cout <<char(Map[i][j] + '0'); cout <<endl; } cout <<endl; } } ; string state[Max] ; int fac[12] = { 0, 1, 2, 6, 24, 120,720, 5040, 40320, 362880, 3628800} ; int kangtuo(kdq a) { int ans = 0 ; Rep(i,0,8) { int num = 0 ; Rep(j,i + 1 ,8) { if(a.Map[i / 3][i % 3] > a.Map[j / 3 ][j % 3]) num ++ ; } ans += num * (fac[8 - i]) ; } return ans ; } int vis[Max] ; int mx[4] = {0,0,1,-1} ; int my[4] = {1,-1,0,0} ; char opp[4] = {'r' ,'l','d','u'} ;//从起点开始搜索时的交换顺序 char dopp[4] = {'l','r','u','d'} ;//从终点开始搜索时的交换顺序 int inmap(kdq a ) { if(a.x >= 0 && a.y <3 && a.x < 3 && a.y >= 0)return 1; return 0 ; } string bfs(kdq s ) { queue<kdq>q ; kdq init ; init.Map[0][0] = 1 ; init.Map[0][1] = 2 ; init.Map[0][2] = 3 ; init.Map[1][0] = 4 ; init.Map[1][1] = 5 ; init.Map[1][2] = 6 ; init.Map[2][0] = 7 ; init.Map[2][1] = 8 ; init.Map[2][2] = 9 ; init.x = 2 ; init.y = 2 ; init.op.clear() ; q.push(s) ;//起点 q.push(init) ;//终点 int ss = kangtuo(s) ; vis[ss] = 2 ;//将从起点开始遍历到的点置为2 ss = kangtuo(init) ; vis[ss] = 1 ;//将从终点开始遍历到的点置为1 while(!q.empty()) { kdq temp = q.front() ; q.pop() ; int cc = kangtuo(temp) ; Rep(i,0,3) { kdq next = temp ; next.x = temp.x + mx[i] ; next.y = temp.y + my[i] ; if(inmap(next)) { swap(next.Map[next.x][next.y] ,next.Map[temp.x][temp.y]) ; int num = kangtuo(next) ; if(!vis[num] )//如果未遍历过该点 { vis[num] = vis[cc] ; if(vis[num] == 1)//如果是终点遍历出来的点 next.op += dopp[i] ; else//同理 next.op += opp[i] ; state[num] = next.op ;//记录当前的路径 q.push(next) ; } else if(vis[num] != vis[cc])//如果该点被起点和终点都遍历到 { string c1 ,c2 ; if(vis[num] == 1) c1 = state[num] ,c2 = state[cc] + opp[i]; else c1 = state[cc] + dopp[i] ,c2 = state[num] ; reverse(c1.begin() ,c1.end()) ;//注意从终点开始遍历的顺序得取反 return c2 + c1 ;//那么返回该点的顺序,即为起点到终点的顺序 } } } } return "unsolvable" ; } char a[10000] ; int main() { while(gets(a)) { int l = strlen(a) ; kdq now ; int tx = 0 ; int numx ,numy ; Rep(i,0,l - 1) { if(a[i] >= '0' && a[i] <= '8') { now.Map[tx / 3] [tx % 3] = a[i] - '0' ; tx ++ ; } else if(a[i] == 'x') { now.Map[tx / 3][tx % 3] = 9 ; numx = tx / 3 ; numy = tx % 3 ; tx ++ ; } if(tx >= 9)break ; } mem(vis,0) ; now.x = numx ; now.y = numy ; now.op.clear() ; printf("%s\n",bfs(now).c_str()) ; } return 0; }