如何解决数独问题,以便通过交换任何两个相邻的子网格,我仍然得到有效的答案?
How to solve a sudoku such that by swapping any two adjacent sub grids I still get a valid answer?
我得到了一个n^2 * n^2网格,里面填充了几个数字。我需要使用基本的数独规则以及另一个附加条件来填充剩余的网格,即确保如果我交换任何 2 个相邻的子网格 (n*n),那么我的整体网格(数独)仍然有效。我正在使用回溯技术来解决它。但我无法满足附加条件。
1 2 | 3 4
3 4 | 1 2
---------
2 1 | 4 3
4 3 | 2 1
2 1 | 3 4
4 3 | 1 2
---------
1 2 | 4 3
3 4 | 2 1
在这里,将左上角的框与左下角的框交换在一起,我仍然得到了答案。同样,如果我们并排或顶部和底部交换任何盒子(如果它们是相邻的),应该是可能的。
请帮助我。以下是从 www.geeksforgeeks.org 中获取的回溯方法的代码
bool SolveSudoku(int grid[N][N])
{
int row, col;
if (!FindUnassignedLocation(grid, row, col))
return true;
for (int num = 1; num <= 9; num++)
{
if (isSafe(grid, row, col, num))
{
grid[row][col] = num;
if (SolveSudoku(grid))
return true;
grid[row][col] = UNASSIGNED;
}
}
return false; // this triggers backtracking
}
bool FindUnassignedLocation(int grid[N][N], int &row, int &col)
{
for (row = 0; row < N; row++)
for (col = 0; col < N; col++)
if (grid[row][col] == UNASSIGNED)
return true;
return false;
}
bool UsedInRow(int grid[N][N], int row, int num)
{
for (int col = 0; col < N; col++)
if (grid[row][col] == num)
return true;
return false;
}
bool UsedInCol(int grid[N][N], int col, int num)
{
for (int row = 0; row < N; row++)
if (grid[row][col] == num)
return true;
return false;
}
bool UsedInBox(int grid[N][N], int boxStartRow, int boxStartCol, int num)
{
for (int row = 0; row < 3; row++)
for (int col = 0; col < 3; col++)
if (grid[row+boxStartRow][col+boxStartCol] == num)
return true;
return false;
}
bool isSafe(int grid[N][N], int row, int col, int num)
{
return !UsedInRow(grid, row, num) &&
!UsedInCol(grid, col, num) &&
!UsedInBox(grid, row - row%3 , col - col%3, num);
}
void printGrid(int grid[N][N])
{
for (int row = 0; row < N; row++)
{
for (int col = 0; col < N; col++)
printf("%2d", grid[row][col]);
printf("n");
}
}
我如何将该条件合并到其中。首先,请让我知道是否有可能通过回溯来解决。"n"的上限是 30。
给定一个有效的数独解决方案,以及其中两个子网格A
和B
,一个在另一个之上(除了另一个),当且仅当它们在每行(resp.columns)上具有相同的元素(以不同的顺序)时,您可以交换A
和B
。(即sort(A[i, :])==sort(B[i, :]
1..n 中的所有 i)。
因此,您需要做的就是添加一些约束,以反映这一点:
- 当您想将值
a
放在A[i, j]
中时(A
子网格),请考虑A
的邻居。给定一个B
高于或低于A
的邻居,如果a
已经在B
中,则移动无效
,与 - 同样适用于 A 的水平邻居(带列)
i
行不同因此,在实践中,您只需要使用更多约束来扩展isSafe()
:)。
它实际上应该比没有 n 的大值约束的运行速度更快,因为您将探索更少的树。
编辑
我会添加函数 UsedInNeighborsWrongRow(rep. 列),例如:
bool UsedInNeighborsWrongRow(int grid[N][N], int boxStartRow, int boxStartCol, int rowIdw, int num)
{
for (int row = 0; row < N; row++)
if (row != rowIdx)
for (int col = 0; col < N; col++)
if (grid[row+boxStartRow][col+boxStartCol] == num)
return true;
return false;
}
并在isSafe
中为每个邻居打电话给他们:
bool isSafe(int grid[N][N], int row, int col, int num)
{
bool OKForSwapping = !UsedInNeighborsWrongRow(grid, neighbor1_row, neighbor1_col, row, num);
if (there is a 2nd vertical neighbor)
OKForSwapping &=!UsedInNeighborsWrongRow(grid, neighbor2_row, neighbor2_col, row, num);
OKForSwapping &=!UsedInNeighborsWrongColumn(grid, neighbor3_row, neighbor3_col, col, num);
if (there is a 2nd horizontal neighbor)
OKForSwapping &=!UsedInNeighborsWrongColumn(grid, neighbor4_row, neighbor4_col, row, num);
return !UsedInRow(grid, row, num) &&
!UsedInCol(grid, col, num) &&
!UsedInBox(grid, row - row%N , col - col%N, num) &&
OKForSwapping;
}
它很长,但我不确定你能做得更好,数独结构更适合其他约束,而不是这个......
警告:您应该在函数UsedInBox
和isSafe
中将 3 替换为 N
相关文章:
- 欧拉项目#8答案是大以获得有效答案
- 首要问题的答案让值班员搞错了
- C++问题:用户认为数字1-100,程序提出问题不超过6次即可得到答案。无法正确
- 我试图制作一个程序,要求用户输入问题和答案,但程序循环不正确
- 使用 bfs 解决连接组件问题时得到错误的答案
- 同一对象的"sizeof"的不同答案
- 使用对象文件读取三角形数据网格
- 递归求和任务的错误答案
- 如何从 Skia 路径几何体中获取网格?
- 我无法在Visual Studio代码中使用CIN输入答案,它说输入您的年龄,但它说只读文本编辑器如何解决这个问题?
- 为什么C++程序在太大时返回代码而不是答案?
- CGAL:如何创建填充边界曲线的曲面网格?
- 检查 2D 网格的某个元素是否与另一个元素共享对角线、水平线或垂直线
- 创建具有两个视口的Qt3D C++场景,其中显示适当的不同网格
- 如何从 3D 曲面网格中删除自相交三角形?
- 不理解为什么代码没有产生所需的答案
- 为什么我在代码厨师的 CMPRSS 问题中得到 WA(错误答案)?
- 在均匀网格中处理碰撞
- 更改高度贴图,使其在 4x4 网格上显示 16 个 hieghtmap
- 如何解决数独问题,以便通过交换任何两个相邻的子网格,我仍然得到有效的答案?