这道题暴力枚举就可过,还是利用处理n皇后的时候的递归思路来解。博客如下
n皇后
题目链接vjudge
每次去从’1’到’9’枚举,然后如果不满足情况就直接剪枝,然后回溯到上一个结点,继续枚举。如果自己写出了bug那么还是直接选择一款比较好用的IDE去调吧.
同时,如果在递归的过程当中已经找到了答案,那么就直接可以直接退出所有的,输出答案。我采用的是用一个bool型flag变量来表明该信息的。详看注释.
dfs(r, c)表示从点(r, c)开始递归
//#include <bits/stdc++.h>
#include <iostream>
#include <string>
using namespace std;
const int border_num = 9;
string sudoku[border_num]; //存储信息
bool flag = false; // 表明是否已经得到答案
bool check(int r, int c, char ch)
{
for (int i = 0; i < border_num; i++)
if (ch == sudoku[r][i])
return false; // 在同一行检查是否有相同的字符
for (int i = 0; i < border_num; i++)
if (ch == sudoku[i][c])
return false; // 在同一列检查是否有相同的字符
for (int i = r / 3 * 3; i < r / 3 * 3 + 3; i++) {
for (int j = c / 3 * 3; j < c / 3 * 3 + 3; j++) {
if (ch == sudoku[i][j])
return false; // 在同一个田字格中是否存在相同的字符
}
}
return true;
}
bool answer()
{
for (int i = 0; i < border_num; i++)
for (int j = 0; j < border_num; j++)
if ('0' == sudoku[i][j])
return false;
return true;
// 如果在棋盘当中没有'0'就认为已经找到了答案
}
void dfs(int r, int c)
{
if (flag) return ; // 如果已经找到了答案,立马退出
if (r == border_num) {
if (answer()) flag = true;
return ;
}
if ('0' == sudoku[r][c]) { // 如果当前可以防止棋子,就进行dfs
for (int ch = '1'; ch <= '9'; ch++) { //从字符'1'到'9'依次递归
if (check(r, c, ch)) {
sudoku[r][c] = ch;
if (c + 1 < border_num)
dfs(r, c + 1); //如果下一个递归点在下一行
else
dfs(r + 1, 0); // 如果下一个递归点依旧在本行
if (!flag) // 防止找到答案结束递归是将答案覆盖
sudoku[r][c] = '0';
}
}
}
else {
if (c + 1 < border_num)
dfs(r, c + 1);
else
dfs(r + 1, 0);
}
}
int main()
{
int q; cin >> q;
while (q--) {
flag = false;
for (int i = 0; i < border_num; i++) cin >> sudoku[i];
dfs(0, 0);
for (int i = 0; i < border_num; i++) cout << sudoku[i] << endl;
}
return 0;
}