BZOJ 1085 SCOI 2005 骑士精神 IDA*

来源:互联网 发布:中学网络安全教育教案 编辑:程序博客网 时间:2024/05/08 23:36

题目大意:有一张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;}


0 0