题目链接 P2324 [SCOI2005]骑士精神
首先,我们先讲讲几个基础知识:
迭代加深
我们假设深度优先搜索(DFS)的最深搜索到Max_depth,那么也就是说深度到达Max_depth的时候不管满不满足答案都要返回了true or false。
IDA*启发式搜索优化DFS
作为A*算法,也就是有估值函数这样的定义了,原来的深度小于等于Max_depth也将剪枝成为当前的深度deep(表示已经走的路程)+至少需要再走的路程(估值)要小于等于Max_depth才可以走,这就是启发式的思想了。
估值函数
这里的估值函数肯定是“差距”了,当然是偏小的,不过这没有关系。
inline int _Det()
{
int sum = 0;
for(int i=0; i<5; i++) for(int j=0; j<5; j++) if(a[i][j] ^ Bas[i][j]) sum++;
return sum;
}
启发式搜索
bool dfs(int x, int y, int deep, int Lim_depth)
{
if(deep == Lim_depth && !_Det()) return true;
else if(deep == Lim_depth) return false;
for(int i=0, xx, yy; i<8; i++)
{
xx = x + dir[i][0]; yy = y + dir[i][1];
if(!In_Map(xx, yy)) continue;
swap(a[x][y], a[xx][yy]);
if(deep + _Det() <= Lim_depth && dfs(xx, yy, deep + 1, Lim_depth)) return true; //at last turn one exchange tuo
swap(a[x][y], a[xx][yy]);
}
return false;
}
这里的判断条件是“deep + _Det() <= Lim_depth”是因为最后一次移动,可能一次性会改变两个值,所以本身应该是“deep + 1 + _Det() - 1 <= Lim_depth”。
Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f3f3f3f3f
#define eps 1e-8
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
#define MAX_3(a, b, c) max(a, max(b, c))
#define MAX_4(a, b, c, d) max(max(a, b), max(c, d))
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int Bas[5][5] =
{
1, 1, 1, 1, 1,
0, 1, 1, 1, 1,
0, 0, 2, 1, 1,
0, 0, 0, 0, 1,
0, 0, 0, 0, 0
};
const int dir[8][2] =
{
-1, -2,
-1, 2,
1, -2,
1, 2,
-2, -1,
-2, 1,
2, -1,
2, 1
};
inline bool In_Map(int x, int y) { return x >= 0 && y >= 0 && x < 5 && y < 5; }
char mp[5][5];
int a[5][5];
inline int _Det()
{
int sum = 0;
for(int i=0; i<5; i++) for(int j=0; j<5; j++) if(a[i][j] ^ Bas[i][j]) sum++;
return sum;
}
bool dfs(int x, int y, int deep, int Lim_depth)
{
if(deep == Lim_depth && !_Det()) return true;
else if(deep == Lim_depth) return false;
for(int i=0, xx, yy; i<8; i++)
{
xx = x + dir[i][0]; yy = y + dir[i][1];
if(!In_Map(xx, yy)) continue;
swap(a[x][y], a[xx][yy]);
if(deep + _Det() <= Lim_depth && dfs(xx, yy, deep + 1, Lim_depth)) return true; //at last turn one exchange tuo
swap(a[x][y], a[xx][yy]);
}
return false;
}
int main()
{
int T; scanf("%d", &T);
while(T--)
{
for(int i=0; i<5; i++)
{
scanf("%s", mp[i]);
for(int j=0; j<5; j++)
{
a[i][j] = mp[i][j] == '*' ? 2 : mp[i][j] - '0';
}
}
if(!_Det()) { printf("0\n"); continue; }
int sx = 0, sy = 0;
for(int i=0; i<5; i++) for(int j=0; j<5; j++)
{
if(a[i][j] == 2) { sx = i; sy = j; break; }
}
bool flag = false;
for(int i=1; i<=15; i++)
{
if(dfs(sx, sy, 0, i))
{
flag = true; printf("%d\n", i);
break;
}
}
if(!flag) printf("-1\n");
}
return 0;
}