CSES「Chessboard and Queens」(八皇后变种)代码始终返回0的问题求助
CSES「Chessboard and Queens」(八皇后变种)代码始终返回0的问题求助
看起来你遇到的问题核心是没有在递归回溯时恢复状态标记,导致一旦标记了行/对角线的占用状态,就再也无法重置,后续的递归分支都无法正常推进到最后一行(y=7),最终ans一直为0。
问题根源分析
你的代码逻辑思路是对的:用三个数组分别标记列、两条对角线的占用状态,递归尝试每一行的合法位置。但关键的疏漏是:
当你在某个位置标记了table1/table2/table3为true并进入下一行递归后,递归返回时没有将这些标记改回false。
举个具体的连锁反应:
- 你在
y=0选了x=0,标记了对应的列和对角线 - 递归进入
y=1,选了某个合法的x,再次标记对应的状态 - 当这个分支的递归完全结束(无论是找到解还是走不通返回),你没有把
y=1的标记重置,导致y=1的其他列位置会被错误地判定为已占用 - 后续所有递归分支都会被错误的标记阻塞,根本无法推进到
y=7的情况,自然ans始终为0
修复后的代码
我帮你修正了核心问题,同时优化了条件判断的可读性:
#include <iostream> #include <string> using namespace std; int ans = 0; string il[8]; // 存储不能放皇后的棋盘位置 void quen(int x, int y, bool table1[15], bool table2[15], bool table3[8]) { // 首先判断当前位置是否是禁放区 if (il[y][x] == '*') { return; } // 检查列、两条对角线是否已被占用 if (table3[x] || table2[x + y] || table1[7 - y + x]) { return; } // 标记当前位置的占用状态 table1[7 - y + x] = true; table2[x + y] = true; table3[x] = true; if (y == 7) { // 走到最后一行,找到一个合法解 ans++; } else { // 递归尝试下一行的所有列 for (int i = 0; i < 8; i++) { quen(i, y + 1, table1, table2, table3); } } // 关键:回溯时恢复状态! table1[7 - y + x] = false; table2[x + y] = false; table3[x] = false; } int main() { for (int i = 0; i < 8; i++) { string str; cin >> str; il[i] = str; } bool table1[15] = {0}; bool table2[15] = {0}; bool table3[8] = {0}; for (int i = 0; i < 8; i++) { quen(i, 0, table1, table2, table3); } cout << ans << endl; return 0; }
关键修改点
- 添加回溯状态恢复:在递归返回后,将之前标记的
table1/table2/table3重置为false,这样当回溯到上一行时,才能尝试下一个列的位置,不会被之前的标记干扰。 - 优化条件判断顺序:先判断当前位置是否是禁放区,再检查占用状态,逻辑更清晰,减少嵌套层级。
额外说明
你原代码中il[y][x]的索引是正确的:il[i]存储的是第i行的输入字符串,y是当前行号,x是列号,所以il[y][x]确实对应棋盘上的(y,x)位置,这部分没有问题。
修复后,测试你提供的示例输入,程序应该能返回正确的合法解数量了。
备注:内容来源于stack exchange,提问作者Boran Alp Yalcin
相关产品推荐
相关产品推荐

