P2324 [SCOI2005] 骑士精神
P2324 [SCOI2005] 骑士精神
大意
最小的步数达到要求的地方。
思路
这个题目的目标状态也很简约,就是形如题目中的样子,这个我们转换思路就是拿着这个空格去和旁边的格子不断的交换,但是这样产生的状态是很多的,为了剪枝,我们采用 IDA*,这个题目的估价函数有个很显然的写法,就是记录错误位置的个数,因此,一定小于等于...吗?我们考虑这样的情况,如果现在只需要一步,将空格和一个棋子交换,这样的实际步数是 \(1\),但是你的估价函数给的是 \(2\),显然不行,特判一下即可。然后我们就正常的去迭代加深的搜索就好。
代码
#include<iostream>
using namespace std;
int T, ans = 1e9;
int a[6][6];
int dx[] = {1, 1, -1, -1, 2, 2, -2, -2};
int dy[] = {2, -2, 2, -2, 1, -1, 1, -1};
int f(int b[6][6]){
int res = 0;
for(int j = 1;j <= 5;j ++){
if(b[1][j] != 1) res ++;
}
for(int j = 1;j <= 5;j ++){
if(b[5][j] != 0) res ++;
}
if(b[2][1] != 0) res ++;
for(int j = 2;j <= 5;j ++){
if(b[2][j] != 1) res ++;
}
if(b[4][5] != 1) res ++;
for(int j = 1;j <= 4;j ++){
if(b[4][j] != 0) res ++;
}
for(int j = 1;j <= 2;j ++){
if(b[3][j] != 0) res ++;
}
if(b[3][3] != 2) res ++;
for(int j = 4;j <= 5;j ++){
if(b[3][j] != 1) res ++;
}
if(res == 2) return 1;
return res;
}
void dfs(int dp, int now, int cnt[6][6]){
if(now >= ans) return;
if(f(cnt) == 0){
ans = now;
return;
}
if(now + f(cnt) > dp) return;
if(now > dp){
return;
}
int sx = 0, sy = 0;
for(int i = 1;i <= 5;i ++){
if(sx) break;
for(int j = 1;j <= 5;j ++){
if(cnt[i][j] == 2){
sx = i, sy = j;
break;
}
}
}
for(int i = 0;i < 8;i ++){
int nx = sx + dx[i];
int ny = sy + dy[i];
if(nx < 1 || ny < 1 || nx > 5 || ny > 5) continue;
int sum[6][6];
for(int p = 1;p <= 5;p ++){
for(int q = 1;q <= 5;q ++){
sum[p][q] = cnt[p][q];
}
}
swap(sum[sx][sy], sum[nx][ny]);
dfs(dp, now + 1, sum);
}
}
int main(){
cin >> T;
while(T --){
for(int i = 1;i <= 5;i ++){
string s; cin >> s;
for(int j = 0;j < 5;j ++){
if(s[j] == '*') a[i][j + 1] = 2;
else a[i][j + 1] = s[j] - '0';
}
}
ans = 1e9;
for(int dp = 1;dp <= 15;dp ++){
dfs(dp, 0, a);
if(ans <= 15) break;
}
if(ans <= 15){
cout << ans << '\n';
}
else{
cout << -1 << '\n';
}
}
return 0;
}
本文来自一名高中生,作者:To_Carpe_Diem

浙公网安备 33010602011771号