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