[SCOI2005] 骑士精神 题解

题目描述

解法

采用 IDA* 算法。不移动骑士而移动空格。每次限制深度,然后对每个遍历到的点进行一次估价,估价函数的值即为当前状态和终点的差异数。

如果估计的加上已经确认的层数比限制搜索的还要多,就直接放弃这个了。

\[\begin{array}{ll} 1 & \textbf{IDA* (point p, w, k) :}\\ 2 & \qquad w \leftarrow f(s).\\ 3 & \qquad \textbf{if } f(s) = 0 :\\ 4 & \qquad \qquad ans \leftarrow g.\\ 5 & \qquad \qquad \textbf{Return.}\\ 6 & \qquad \textbf{if } ans \text{ have a value } \textbf{or } (w + g)\ge k :\\ 7 & \qquad \qquad \textbf{Return.}\\ 8 & \qquad \textbf{for} \text{ every legal position of }(x, y):\\ 9 & \qquad \qquad \text{swap}(p, (x,y)).\\ 10 & \qquad \qquad \text{IDA*}((x,y),w+1,k).\\ 11 & \qquad \qquad \text{swap}(p, (x,y)).\\ \end{array} \]

代码

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int tg[6][6] = {
	{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}
};

int g[6][6];

int f() {
	int cnt = 0;
	for(int i = 1; i <= 5; i ++)
		for(int j = 1; j <= 5; j ++)
			if(g[i][j] != tg[i][j])
				cnt ++;
	return cnt;
}

inline int safe(int x, int y){
    if(x < 1 || x > 5 || y < 1 || y > 5) return 0;
    return 1;
}

int dx[9] = {1, 1, -1, -1, 2, 2, -2, -2};
int dy[9] = {-2, 2, 2, -2, 1, -1, -1, 1};

int ans;

void dfs(int k, int x, int y, int w) {
	int val = f();
	if(!val) {
		ans = w;
		return;
	}
	if(w + val > k || ans || w == k) return;
	for(int i = 0; i < 8; i ++) {
		int X = x + dx[i];
		int Y = y + dy[i];
		if(!safe(X, Y)) continue;
		swap(g[x][y], g[X][Y]);
		dfs(k, X, Y, w + 1);
		swap(g[x][y], g[X][Y]);
	}
}

void solve() {
	int x = 0, y = 0;
	ans = 0;
	for(int i = 1; i <= 5; i ++)
		for(int j = 1; j <= 5; j ++) {
			char ch;
			cin >> ch;
			if(ch == '*') x = i, y = j, g[i][j] = 2;
			else g[i][j] = ch - '0';
		}
	if(!f()) {
		printf("0\n");
		return;
	}
	for(int k = 1; k <= 16; k ++) {
		dfs(k, x, y, 0);
		if(ans) {
			printf("%d\n", ans);
			return;
		}
	}
	printf("-1\n");
}

int main() {
	int t;
	cin >> t;
	while(t --) solve();
}
posted @ 2022-10-07 17:14  Inversentropir-36  阅读(18)  评论(0编辑  收藏  举报