题目
输入输出格式
输入格式:
第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。
输出格式:
对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。
输入输出样例
输入样例#1:
2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
输出样例#1:
7
-1
题解
- 模拟赛考的题,不会$IDA*$的我只能打玄学爆搜,后来加了波优化在洛谷上得了$30pts$,
wtcl - 我们来$bb$正解吧
- 前置技能
- 迭代加深搜索讲解qwq
- 估价函数:
- 定义$f(n)=g(n)+h(n)$。$f(n)$是对$n$节点的估价函数,$g(n)$是当前走到$n$节点的实际代价,$h(n)$是你的估计函数值
- 那么$A*$最关键的还是设计估价函数。
- 本题我们采用的估价函数为当前状态与目标状态的每个点不同的个数
- 证明的话可以感性的理解一下
- 具体实现为如果$f(n)=g(n)+h(n)>maxd$即当前估价函数大于深度限制就return
$code$
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10;
template <class T>
inline void read(T &s) {
s = 0;
T w = 1, ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
s *= w;
}
int T, s, t;
int a[maxn][maxn];
bool flag = false;
const int b[maxn][maxn] = {
{ 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 1, 1 },
{ 0, 0, 1, 1, 1, 1 },
{ 0, 0, 0, 2, 1, 1 },
{ 0, 0, 0, 0, 0, 1 },
{ 0, 0, 0, 0, 0, 0 },
};
const int dx[8] = { 1, 1, 2, 2, -1, -1, -2, -2 };
const int dy[8] = { 2, -2, 1, -1, 2, -2, 1, -1 };
inline int get_H() {
int cnt = 0;
for (int i = 1; i <= 5; ++i)
for (int j = 1; j <= 5; ++j)
cnt += !(a[i][j] == b[i][j]);
return cnt;
}
inline bool check(int x, int y) {
if (x < 1 || x > 5 || y < 1 || y > 5) return false;
else return true;
}
void dfs(int now, int high, int x, int y) {
if (now == high) {
if (!get_H()) { flag = true; return ; }
}
for (int i = 0; i < 8; ++i) {
int xx = x + dx[i], yy = y + dy[i];
if (!(check(xx, yy))) continue;
swap(a[xx][yy], a[x][y]);
if (get_H() + now - 1 < high)
dfs(now + 1, high, xx, yy);
swap(a[xx][yy], a[x][y]);
}
}
int main() {
read(T);
while (T--) {
s = 0; t = 0; flag = false;
memset(a, 0, sizeof(a));
for (int i = 1; i <= 5; ++i) {
for (int j = 1; j <= 5; ++j) {
// char ch = getchar();
char ch; cin >> ch;
if (ch == '*') { a[i][j] = 2, s = i, t = j; }
else a[i][j] = (int)(ch - '0'); /* 0 refers to white 1 rft black 2 rft empty */
}
// getchar();
}
if (!get_H()) { puts("0"); continue; } /* If the current situation is equal, direct output 0 */
for (int idt = 1; idt <= 15; ++idt) {
dfs(0, idt, s, t);
if (flag) {
printf("%d\n", idt); break;
}
}
if (!flag) puts("-1");
}
return 0;
}
或者用严格限制的dfs,即每次dfs对产生结果进行估价,价低了就dfs。。
不,这个比洛谷严,看来我只能用双向BFS+A*了。。
为什么你的代码会超时?