在考试的时候没写出来,很气,(就差临门一脚,废了40min最后一分没拿着)就差最后的检验交叉,不知道有什么活可以完成,于是考完之后猛攻了一手整出狠活,也是解决了。想法不多说,代码注释很详细:
#include<algorithm>
#include<iostream>
#include<vector>
#include<cmath>
#include<cstring>
#include<stdio.h>
#include<string>
#include<math.h>
using namespace std;
#define MAX_N 11 // 最大棋盘尺寸为11x11
#define MAX_PATH 105 // 最长可能路径长度
int N, K; // N是棋盘的大小,K是数字序列的周期
int grid[MAX_N][MAX_N]; // 存储棋盘上的数字
char best_path[MAX_PATH]; // 存储字典序最小的路径
bool visited[MAX_N][MAX_N]; // 标记棋盘格是否已访问
bool crosses[MAX_N][MAX_N][MAX_N][MAX_N]; // 用于检测路径交叉
// 方向向量:上, 右上, 右, 右下, 下, 左下, 左, 左上
int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1};
int dy[] = {0, 1, 1, 1, 0, -1, -1, -1};
// 检查(x, y)是否是有效的下一步位置
bool is_valid(int x, int y) {
return x >= 0 && x < N && y >= 0 && y < N && !visited[x][y];
}
// 更新交叉检测数组
void update_crosses1(int x, int y, int nx, int ny, bool state,int dir) {
if (dir == 1 || dir == 3 || dir == 5 || dir == 7) {
if(x<nx){
crosses[x+1][y][nx-1][ny] = crosses[nx-1][ny][x+1][y] = state;
}
else{
crosses[x-1][y][nx+1][ny] = crosses[nx+1][ny][x-1][y] = state;
}
}
}
// 使用深度优先搜索找到满足条件的路径
void dfs(int x, int y, int step, char *path, int next_num) {
// 如果已经找到最优解,且当前路径字典序已经不可能更小
if (best_path[0] != '\0' && strncmp(path, best_path, step - 1) >= 0) {
return; // 如果当前路径已不优于最佳路径,则剪枝
}
// 如果到达目的地且所有格子都访问过,检查是否更新最佳路径
if (x == N-1 && y == N-1 && step == N*N) {
path[step - 1] = '\0'; // 确保字符串以null字符结束
if (strlen(best_path) == 0 || strcmp(path, best_path) < 0) {
strcpy(best_path, path); // 更新最优路径
}
return;
}
// 尝试八个可能的方向
for (int dir = 0; dir < 8; dir++) {
int nx = x + dx[dir];
int ny = y + dy[dir];
// 移动到新位置前检查有效性和数字匹配
if (is_valid(nx, ny) && grid[nx][ny] == next_num && !crosses[x][y][nx][ny]) {
visited[nx][ny] = true; // 标记新位置为已访问
update_crosses1(x, y, nx, ny, true, dir); // 更新交叉检测数组
path[step - 1] = '0' + dir; // 记录方向数字到路径中
dfs(nx, ny, step + 1, path, (next_num + 1) % K); // 继续探索
visited[nx][ny] = false; // 回溯,撤销访问标记
update_crosses1(x, y, nx, ny, false, dir); // 恢复交叉检测数组
}
}
}
int main() {
scanf("%d %d", &N, &K); // 读入棋盘大小和数字周期
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
scanf("%d", &grid[i][j]); // 填充棋盘数据
}
}
if(N == 1 && K == 1)
{
if(grid[0][0] == 0) cout << '0';
else cout << '1';
return 0;
}
memset(visited, false, sizeof(visited)); // 初始化访问标记数组
memset(crosses, false, sizeof(crosses)); // 初始化交叉检测数组
best_path[0] = '\0'; // 初始化最优路径
char path[MAX_PATH]; // 当前路径字符串
visited[0][0] = true; // 标记起点为已访问
path[0] = '\0'; // 清空路径字符串
if (grid[0][0] == 0) {
dfs(0, 0, 1, path, 1 % K); // 从(0,0)开始探索
}
// 输出最佳路径或-1表示无解
if (strlen(best_path) > 0) {
printf("%s\n", best_path);
} else {
printf("-1\n");
}
return 0;
}
也是过掉了的,dashoj.com很好,推荐一用
想了想也不是一分没拿,-1碰瓷儿应该也有分,不过白瞎我的心了。。。。。。