洛谷P2324 [SCOI2005] 骑士精神
方法很多,最经典的是用搜索的算法,也就是\(IDA*\)算法搜索。
\(IDA*\)算法是每次规定一个搜索深度,并在搜索的时候限制该搜索深度,从而达到把深搜的优点和广搜的优点结合起来优化时间的一个算法。
说白了,就是一个剪枝借鉴了广搜的思想。
#include <bits/stdc++.h>
using namespace std;
int di[60] = {1, -1, 2, -2, 1, -1, 2, -2};
int dj[60] = {2, 2, 1, 1, -2, -2, -1, -1};
int T, t, ans, si, sj;
int dp[10][10], data[10][10];
bool flag;
int enda[10][10] = {
{0, 0, 0, 0, 0, 0},
{0, 2, 2, 2, 2, 2},
{0, 1, 2, 2, 2, 2},
{0, 1, 1, 0, 2, 2},
{0, 1, 1, 1, 1, 2},
{0, 1, 1, 1, 1, 1},
};
inline bool cut(int nt)
{
int dis = 0;
for (int i = 1; i <= 5; i++)
for (int j = 1; j <= 5; j++)
if (data[i][j] != enda[i][j])
dis++;
if (dis + nt > t) return 0;
else return 1;
}
bool dfs(int nt, int i, int j)//nt就是当前深度
{
if (nt == t)//判断最终深度是否都已经到达最终的目标。
{
for (int i = 1; i <= 5; i++)
for (int j = 1; j <= 5; j++)
if (data[i][j] != enda[i][j])
return 0;
flag = 1;
}
if (flag) return 1;
for (int o = 0; o < 8; o++)
{
int ni = i + di[o], nj = j + dj[o];
if (ni <= 0 || ni > 5 || nj <= 0 || nj > 5) continue;
swap(data[i][j], data[ni][nj]);
if (cut(nt)) //剪枝,如果连最优的走法都走不过去就不能走了
bool a = dfs(nt + 1, ni, nj);
swap(data[i][j], data[ni][nj]);
}
return 0;
}
int main()
{
scanf("%d", &T);
while (T--)
{
ans = 0;
for (int i = 1; i <= 5; i++)
for (int j = 1; j <= 5; j++)
{
char c;
cin >> c;
if (c == '*') data[i][j] = 0, si = i, sj = j;
if (c == '0') data[i][j] = 1;
if (c == '1') data[i][j] = 2;
}
for (t = 1; t <= 15; t++)
{
if (ans) break;
flag = 0;
dfs(0, si, sj);
if (flag) ans = t;
}
printf("%d\n", ans ? ans : -1);
}
return 0;
}
/*
1
11111
01110
00*11
00001
00000
*/