【题解】luogu P2324 [SCOI2005] 骑士精神

发布时间 2023-07-26 20:14:00作者: marti88414

题目传送门:luogu P2324 [SCOI2005] 骑士精神

题意

图片

分析

数据范围比较小,适合搜索,但是没办法bfs,考虑迭代加深的dfs

题解

首先将问题转化为空格向八个方向跳,直接暴力dfs会爆T,考虑 \(A^*\) 搜索,代价函数为当前状态与目标相差的棋子数量

AC代码

#include<bits/stdc++.h>
#define int long long
#define pii pair<int, int>
#define cin std::cin
#define cou std::cout
using namespace std;
const int inf = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
int n, m, k;
char c[15][15], ans[5][5] = {{'1', '1', '1', '1', '1'}, {'0', '1', '1', '1', '1'}, {'0', '0', '*', '1', '1'}, {'0', '0', '0', '0', '1'}, {'0', '0', '0', '0', '0'}};
int cntx[] = {1, 1, 2, 2, -1, -1, -2, -2};
int cnty[] = {2, -2, 1, -1, 2, -2, 1, -1};

inline void init() {
    // cnt = 0;
}

bool cmp() {
    for(int i = 0; i < 5; ++i) {
        for(int j = 0; j < 5; ++j) {
            if(c[i][j] != ans[i][j]) return false;
        }
    }
    return true;
}

bool ax(int step, int dep) {
    int cnt = 0;
    for(int i = 0; i < 5; ++i) {
        for(int j = 0; j < 5; ++j) {
            if(c[i][j] != ans[i][j]) {
                cnt ++;
                if(cnt + step > dep + 1) return false;
            }
        }
    }
    return true;
}

inline bool dfs(int x, int y, int cur, int dep) {
    
    if(cur == dep) {
        if(cmp()) return true;
        else return false;
    }
    if(!ax(cur, dep)) return false;
    for(int i = 0; i < 8; ++i) {
        if(x + cntx[i] >= 0 && x + cntx[i] < 5 && y + cnty[i] >= 0 && y + cnty[i] < 5) {
            c[x][y] = c[x + cntx[i]][y + cnty[i]];
            c[x + cntx[i]][y + cnty[i]] = '*';
            if(dfs(x + cntx[i], y + cnty[i], cur + 1, dep)) return true;
            c[x + cntx[i]][y + cnty[i]] = c[x][y];
            c[x][y] = '*';
        } 
    }
    return false;
}

inline void solve() {
    int x = -1, y = -1;
    for(int i = 0; i < 5; ++i) {
        for(int j = 0; j < 5; ++j) {
            cin >> c[i][j];
            if(c[i][j] == '*') x = i, y = j;
        }
    }
    int dep = 0;
    while(!dfs(x, y, 0, dep) && dep <= 15) {
        dep ++;
    }
    if(dep > 15) cout << -1 << endl;
    else cout << dep << endl;
    return;
}

signed main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    while(T --) {
        init();
        solve();
    }
    return 0;
}