题目大意:有一张5*5的棋盘,上面有12和黑棋还有12个白棋。问最少多步可以到达目标状态。
思路:搜索+剪枝。至于剪枝我就用ID+A*的组合了,因为都不难想,估价函数就是当前图和目标图有多少个方块不一样。如果当前步数+估价大于当前迭代加深的层数就退出。
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int dx[] = {0,1,1,2,2,-1,-1,-2,-2}; const int dy[] = {0,2,-2,1,-1,-2,2,-1,1}; int cases; char src[10][10],aim[10][10]; void Pretreatment() { for(int i = 1; i <= 5; ++i) aim[1][i] = '1',aim[5][i] = '0'; for(int i = 2; i <= 5; ++i) aim[2][i] = '1'; aim[3][4] = aim[3][5] = aim[4][5] = '1'; for(int i = 1; i <= 4; ++i) aim[4][i] = '0'; aim[3][1] = aim[3][2] = aim[2][1] = '0'; aim[3][3] = '*'; } bool IDA_(int deep,int max_deep) { int difference = 0; int x,y; for(int i = 1; i <= 5; ++i) for(int j = 1; j <= 5; ++j) { if(src[i][j] == '*') x = i,y = j; difference += (src[i][j] != aim[i][j]); } if(!difference) return true; if(difference - 1 + deep > max_deep) return false; for(int i = 1; i <= 8; ++i) { int fx = x + dx[i]; int fy = y + dy[i]; if(fx <= 0 || fy <= 0 || fx > 5 || fy > 5) continue; swap(src[x][y],src[fx][fy]); if(IDA_(deep + 1,max_deep)) return true; swap(src[x][y],src[fx][fy]); } return false; } int main() { Pretreatment(); for(cin >> cases; cases; --cases) { for(int i = 1; i <= 5; ++i) scanf("%s",src[i] + 1); bool flag = false; for(int i = 0; i <= 15 && !flag; ++i) { if(IDA_(0,i)) { flag = true; printf("%d\n",i); } } if(!flag) puts("-1"); } return 0; }
时间: 2024-11-03 02:51:52