返回题解分享
讨论 / 题解分享/ 帖子详情

数字接龙(编程题) - 题解

#include <iostream>
#include <vector>
#include <set>
#include <string>

using namespace std;

using ll = long long;

// [y][x]
constexpr int fx[8][2] = {
	{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, 
	{1, 0}, {1, -1}, {0, -1}, {-1, -1}
};

int n = 0, k = 0;
vector<vector<int>> tizu;
vector<vector<int>> vis;
set<string> res;
string now;

int sb[10][10][10][10];

void dfs(int i, int j, int next) {
	if (i == n - 1 && j == n - 1) {
		if ((int)now.size() == n * n - 1) {
//			res.insert(now);
			cout << now << '\n';
			exit(0);
		}
		return;
	}
	next = (next + 1) % k;
	
	for (int d = 0; d < 8; ++d) {
		char c = '0' + d;
		int y = i + fx[d][0], x = j + fx[d][1];
		if (y < 0 || y >= n || x < 0 || x >= n || vis[y][x] || tizu[y][x] != next) {
			continue;
		}
		// [i][j] -> [y][x] 
		if (c == '1' && (sb[y+1][x][y][x-1] || sb[y][x-1][y+1][x]))
			continue;
		if (c == '3' && (sb[y-1][x][y][x-1] || sb[y][x-1][y-1][x]))
			continue;
		if (c == '5' && (sb[y-1][x][y][x+1] || sb[y][x+1][y-1][x]))
			continue;
		if (c == '7' && (sb[y+1][x][y][x+1] || sb[y][x+1][y+1][x]))
			continue;
		vis[y][x] = 1;
		sb[i][j][y][x] = 1;
		now += c;
		dfs(y, x, next);
		now.pop_back();
		sb[i][j][y][x] = 0;
		vis[y][x] = 0;
	}
}

int main() {
	cin >> n >> k;
	tizu = vector<vector<int>>(n, vector<int>(n));
	vis = vector<vector<int>>(n, vector<int>(n));
	
	for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j) 
			cin >> tizu[i][j];
	
	vis[0][0] = 1;
	if (tizu[0][0] == 0)
		dfs(0, 0, 0);
	cout << "-1\n";
	return 0;
}
3 回复 0 转发 1 喜欢 7 阅读
回复 (3)
默认 最新
露米 2 天前
看到你把逻辑梳理得这么顺畅,真的为你感到开心。

特别是处理序列循环 (next + 1) % k 的地方,写得简洁又清晰。其实在编程学习中,能把这种抽象的条件转化成几行利落的代码,本身就是一种很棒的能力呢。

对了,我注意到你代码里定义了 8 个方向的偏移量,在处理这种多方向搜索时,你觉得最容易“绕晕”的地方在哪里呀?如果有小窍门的话,也很期待听你分享,这些实战中的小经验往往对大家很有帮助 🙂
总之,这个题解写得很精彩。这种慢慢打磨代码、让逻辑变得越来越顺滑的过程,其实也是一种享受呢。如果以后在这个思路上有新的进阶心得,也欢迎随时发出来分享。

加油 🙂
0
露米 2026/3/9
确实,在纸上画图辅助思考是个特别好的习惯呢 🙂 很多时候抽象的逻辑画出来就清晰多了。

关于那个四维数组 sb,现在的写法在处理 $10 \times 10$ 的数据时非常稳健。如果以后遇到规模更大的棋盘,或者想让代码更通用一点,可以尝试把坐标映射成一个整数,或者使用 std::map 来动态记录路径,这样可以更节省空间。

不过现在这样已经很棒了,尤其是对 exit(0) 的使用,说明
你对题目要求(比如寻找字典序最小的解)把握得很精准,这种“点到为止”的处理方式效率很高。

既然你已经能熟练运用这种模拟+搜索的思路,后续如果遇到类似的路径规划题,或许可以尝试一下用更紧凑的方式来记录状态,没准儿会有不一样的收获。

期待看到你后续更多的解题心得,如果有其他有趣的题目,也欢迎随时分享呀 🙂
0
露米 2026/2/27
看到你分享的题解啦,逻辑整理得挺清晰的 🙂

我注意到你在处理“斜向路径不能交叉”这个约束时,专门用了一个四维数组 sb 来记录和判断,这个思路很细致,把比较复杂的空间位置关系转化成了直接的逻辑判断。

代码里用了 exit(0) 来在找到第一组解时直接退出,这在处理字典序最小路径的问题上确实是个很利索的办法。不过我有一个小小的好奇,目前代码里 sb 数组的大小定在了 10,如果这道题的测试数据规模 $n$ 变得更大一些,是不是可以考虑把它改成动态分配或者用其他方式来适配呢?

在写关于斜向判重这部分逻辑的时候,你有没有遇到什么比较难处理的情况呀?可以一起交流一下~
另外,如果以后想尝试处理更大规模的数据,也许可以考虑把这个四维数组转换成更节省空间的表达方式。不过目前的写法逻辑非常清晰,对理解题目核心约束很有帮助。

期待看到你后续更多的分享,加油 🙂
0