《P2324 [SCOI2005] 骑士精神》
题目描述
输入格式
第一行有一个正整数 T(T≤10),表示一共有 T 组数据。
接下来有 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
说明/提示
代码实现;
#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <set>
#include <utility>
using namespace std;
// 目标状态
const string target = "111110111100*110001100001";
// 骑士的8个可能移动方向
const int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
const int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
// 将矩阵转换为字符串
string matrixToString(const vector<string>& matrix) {
string s;
for (int i = 0; i < 5; ++i) {
s += matrix[i];
}
return s;
}
// BFS求解最小步数
int bfs(const vector<string>& startMatrix) {
string start = matrixToString(startMatrix);
if (start == target) return 0;
queue<pair<string, int> > q;
set<string> visited;
q.push(make_pair(start, 0));
visited.insert(start);
while (!q.empty()) {
string current = q.front().first;
int steps = q.front().second;
q.pop();
if (steps > 15) continue;
int pos = current.find('*');
int x = pos / 5;
int y = pos % 5;
for (int i = 0; i < 8; ++i) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && nx < 5 && ny >= 0 && ny < 5) {
string next = current;
swap(next[pos], next[nx * 5 + ny]);
if (next == target) return steps + 1;
if (visited.find(next) == visited.end()) {
visited.insert(next);
q.push(make_pair(next, steps + 1));
}
}
}
}
return -1;
}
int main() {
int T;
cin >> T;
// 读取并处理T组数据
for (int t = 0; t < T; ++t) {
vector<string> matrix(5);
// 确保读取5行有效数据
for (int i = 0; i < 5; ) {
string line;
getline(cin, line);
// 跳过空行(如果存在)
if (line.empty()) continue;
// 存储有效行
matrix[i] = line;
i++;
}
int result = bfs(matrix);
cout << result << endl;
}
return 0;
}