为什么我的数独程序不返回输出?
Why doesn't my Sudoku program return an output?
因此,我试图通过回溯算法实现sudoku。我不明白为什么我的代码没有给出预期的输出。
我所做的是,我创建了一个循环,其中它在Sudoku中检查一个空单元(以0代表(。正如它发现的那样,它的坐标传递给了一个称为可能的entriesCheck((的函数。该函数将其写入一个称为可能的元素[9]的全球声明的数组,该数字最初可能会填充到该单元格中。
我从这些视频中学到了这种算法:https://www.youtube.com/watch?v=nuodn41ak3ghttps://www.youtube.com/watch?v=qi0diwmx3oy
预期的输出是已解决的Sudoku。它不会预期。相反,它冻结了。一点帮助将意味着很多。谢谢。
#include <stdio.h>
#include <stdlib.h>
int board[9][9] = {
{3, 0, 6, 5, 0, 8, 4, 0, 0},
{5, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 7, 0, 0, 0, 0, 3, 1},
{0, 0, 3, 0, 1, 0, 0, 8, 0},
{9, 0, 0, 8, 6, 3, 0, 0, 5},
{0, 5, 0, 0, 9, 0, 6, 0, 0},
{1, 3, 0, 0, 0, 0, 2, 5, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 4},
{0, 0, 5, 2, 0, 6, 3, 0, 0},
};
int possibleEntries[9];
void possibleEntriescheck(int i, int j)
{
int x,a=0,k,l,y;
for(x=0;x<9;x++)
possibleEntries[x]=0;
for(x=0;x<9;x++)
{
if(board[i][x]!=0)
possibleEntries[board[i][x]-1]=1;
}
for(x=0;x<9;x++)
{
if(board[x][j]!=0)
possibleEntries[board[x][j]-1]=1;
}
if(i==0 || i==1 || i==2)
k=0;
else if(i==3 || i==4 || i==5)
k=3;
else
k=6;
if(j==0 || j==1 || j==2)
l=0;
else if(j==3 || j==4 || j==5)
l=3;
else
l=6;
for(x=k;x<k+3;x++)
{
for(y=l;y<l+3;y++)
if(board[x][y]!=0)
possibleEntries[board[x][y]-1]=1;
}
for(x=0;x<9;x++)
{
if(possibleEntries[x]==0)
possibleEntries[x]=x+1;
else
possibleEntries[x]=0;
}
}
int isFull()
{
int i,j;
for(i=0;i<9;i++)
{
for(j=0;j<9;j++)
{
if(board[i][j]==0)
return 0;
}
}
return 1;
}
void solveSudoku()
{
int i,j,x,b=0,k;
if(isFull())
{
printf("The sudoku board is:n");
for(i=0;i<9;i++)
{
for(j=0;j<9;j++)
printf("t%d",board[i][j]);
printf("n");
}
}
else
{
for(i=0;i<9;i++)
{
for(j=0;j<9;j++)
{
if(board[i][j]==0)
{
possibleEntriescheck(i,j);
for(x=0;x<9;x++)
{
if(possibleEntries[x]!=0)
{
board[i][j]=possibleEntries[x];
solveSudoku();
board[i][j]=0;
}
}
}
}
}
}
return;
}
int main()
{
solveSudoku();
}
您实现了错误的回溯。正如视频中解释的那样,实际算法应该看起来像这样:
solve():
if the sudoku is solved
print field
terminate
x,y = the next vacant field
for each possible value in that field
assign value to x,y
call solve() recursively to try with the assigned value
clear vacant field
现在您的代码所做的是
solve():
if the sudoku is solved
print field
return
for each field in the sudoku
if field is vacant
for each possible value
assign value
solve recursively
reset field to unassigned
现在,这实际上是解决了sudoku。但是这种方法有两个问题:
a :一旦解决了Sudoku,就不会终止。实际上,这个错误也在视频中列出的代码中。递归调用中的一个简单的return
将终止当前呼叫上的方法,并继续进行递归"上方调用"。因此,基本上,算法在>每个中求解了sudoku(前提是有多个,否则,它只是尝试任何可能分配值的方法(。
b :这更严重。您的算法不仅生成所有可能的解决方案,而且还尝试分配可能找到的值的所有顺序。开销是巨大的,这是您的代码根本没有终止的原因。解决sudoku曾经已经花费了很长时间,但是您的代码确实很少。
如果您解决了这些问题,则应发现您的代码可行,只要其余即正确实施即可。我还建议您优化对空置字段的搜索和测试是否为空,因为这些字段可以相当简单,并且会提供一些加速。在开始时生成一个空置字段列表,在其上迭代(每个递归级别的一个字段(,并在处理整个列表后终止。例如:
solve(vacant, count):
if count == 0
print the field
terminate
x, y = vacant[count]
count++
for each possible value assignable to the field
assign value to x, y
call solve(vacant, count) recursively
clear field
您将遇到的另一个问题,这将是相当丑陋的调试,这要归功于这一行:
int possibleEntries[9];
至少可以说,在递归中使用和覆盖的全局变量是一个坏主意。想象一下这样的程序的可能运行(Ident表示递归级别,没有身份意味着动作是全局的(:
solve
|
---> board empty? Nope
x,y <- next vacant field
possible values <- possible values for x, y
field[x, y] <- first value from possible values
solve
|
---> board empty? Nope
x, y <- next vacant field
possible values <- possible values for x, y (overwrites global variable!!!)
field[x, y] <- first value from possible values
solve
|
---> ...
<--- return
field[x, y] <- second value from possible values (WRONG!!!)
...
最后一个分配不会使用您当前正在处理的字段生成的可能值的列表,而是您在返回之前访问了递归中某个地方的另一个字段。您可以通过两种方式解决此问题:
- 迭代从1到9,并分别检查每个数字是否可以分配给字段
- 保留每个递归级别的单独列表
- 这是使用回溯的 nqueen 问题,但我使用了动态 2d 数组,我的程序编译良好,但不返回任何输出
- 返回 str vs. str.substr(0,str.size()) 在 leetcode 中给了我不同的输出
- C++输出参数与返回值
- cpp 返回具有相同输入的不同输出
- 显示C++输出而不返回值
- 简单函数并不总是返回预期的输出
- 输出返回编号。等于输入字符串的单词的字符串数
- 如何在C++中执行命令并获取命令的返回代码标准输出和标准
- 我的动态链接队列在同一输出流中调用时不正确地输出三个返回函数
- 为什么 boost::locale::to_title 不返回预期的输出?
- 在函数中连接两个字符,并在 C++ 中返回输出
- 为什么我的数独程序不返回输出?
- 如何将变量传递给父,但也返回输出值?(C )
- C++字符返回输出符号
- MSSQL服务器存储过程在从c++调用时不返回输出参数
- c++中的字符串返回类型不返回输出
- 从文本文件返回输出的函数
- 在vc++中使用CreateProcess和CreatePipe来执行进程并以字符串形式返回输出
- 从bash脚本返回输出到调用c++函数
- 如何更改用户输入字符,例如。"abcDEF"并返回输出"222333"