http://poj.org/problem?id=1077 /* procedure dfs(depth:longint); begin if 要剪枝 then exit; if 可行 then Print; if Depth<MaxDepth then dfs(depth+1); end; procedure Iterative_Deepening; begin MaxDepth:=0; while true do begin inc(MaxDepth); dfs(1); end; end; */ #include <iostream> #include <math.h> using namespace std; struct Status { int board[3][3]; int px,py; }; Status init,target={1,2,3,4,5,6,7,8,9,2,2}; int targetPos[10][2],path[10000],maxDepth; int move[4][2]={0,-1,-1,0,0,1,1,0}; /* *奇偶剪枝 *每移动一次X方块,必定需要移动一次另外的方块 *所以其他方块需要移动的次数+X方块移动的次数必定是偶数 */ bool IsSolvable() { int i,j,k=0,sum=0,array[9]; for(i=0; i!=3; ++i) for(j=0; j!=3; ++j) array[k++] = init.board[i][j]; //除了X结点外,要到达目标位置需要移动的最大步数,因为在转换成了一维后原本可以上下移动的都被转化成了水平移动. //但是幸运的是,他们是同奇同偶的.具体的证明我也不知道,画图有这么个规律 for(i = 0; i != 8; ++i) for(j = i + 1; j != 9; ++j) if(array[i] > array[j]) sum++; //这个是X方块到目标位置的最短步数,不管怎么移动,只要最后是在目标位置,必定是同奇同偶的.(简单的考虑就是撤销) //而每一次的其他方块的移动都是与X方块的交换来实现的,所以他们的和必定是偶数 sum += abs(init.px - targetPos[9][0]) + abs(init.py - targetPos[9][1]); return sum % 2 == 0; } // heuristic function //计算该状态需要移动的距离 int H(Status &s) { int sum=0, tmp; for(int i = 0; i != 3; ++i) for(int j = 0; j != 3; ++j) { tmp = s.board[i][j]; if(tmp < 9) sum += abs(i - targetPos[tmp][0]) + abs(j-targetPos[tmp][1]); } return sum; } void Output(int depth) { for(int i=0; i < depth; ++i) if(path[i] == 0) cout<<'l'; else if(path[i] == 1) cout<<'u'; else if(path[i] == 2) cout<<'r'; else cout<<'d'; } bool IDAStar(Status &s, int depth, int h, int prev) { if(memcmp(&s, &target, sizeof(Status)) == 0) { Output(depth); return true; } if(depth >= maxDepth) return false; Status ns; int nh,nx,ny,tmp; //next status for(int k = 0; k != 4; ++k) { //这里会撤销上一步的移动,跳过 if(abs(k - prev) == 2) continue; ns = s; nx = s.px + move[k][0]; ny = s.py + move[k][1]; //越界 if(nx < 0 || ny < 0 || nx == 3 || ny == 3) continue; //移动操作 tmp = s.board[nx][ny]; ns.board[s.px][s.py] = tmp; ns.board[nx][ny] = 9; ns.px = nx; ns.py = ny; //向上移动,并且x在与他交换的方块的目标位置的上方,也就是说,与他交换的方块理目标位置近了一步 //可能在上方也可能就是那个位置了 if(k == 0 && ny < targetPos[tmp][1]) nh = h - 1; // l else if(k == 1 && nx < targetPos[tmp][0]) nh = h - 1; // u else if(k == 2 && ny > targetPos[tmp][1]) nh = h - 1; // r else if(k == 3 && ny < targetPos[tmp][0]) nh = h - 1; // d else nh = h + 1; //走歪路了. //不是合法结点.h(n) + g(n) > f(n).. if(depth + nh >= maxDepth) continue; path[depth] = k; if(IDAStar(ns, depth+1, nh, k)) return true; } return false; } int main() { char tmp; int index=0; for(int i = 0; i != 3; ++i) for(int j = 0; j != 3; ++j) { cin>>tmp; if(tmp == 'x') { tmp = '9'; init.px = i; init.py = j; } init.board[i][j] = tmp - '0'; targetPos[++index][0] = i; targetPos[index][1] = j; } if(IsSolvable()) { int h = H(init); //迭代加深,搜索深度作为限制,这个算法还不是很了解..迭代加深.. for(maxDepth = h; ; maxDepth++) if(IDAStar(init, 0, h, -10)) break; } else cout<<"unsolvable"; return 0; }