C 如何从回溯算法中删除垃圾值?

C 如何从回溯算法中删除垃圾值?,c,arrays,algorithm,C,Arrays,Algorithm,在我提问之前,我的英语不好,所以很难理解我的单词 我一直在想如何用位运算符解数独。 第一个想法是声明一个三维数组,添加九个适合9-9的数字,并排除与任何坐标对应的行、列和框的数量。 然而,我认为使用位运算符可以进一步降低执行速度 例如,如果数独的一列中的数字是1,我认为它是2的双平方。这相当于0000 0000 0010。 接下来,4将被宣布为16,2的第四个正方形。 这相当于0000 0001 0000 让我们假设所有以这种方式提供的数独都被转换成二进制。 例如,如果第一行是1,2,5/0,8

在我提问之前,我的英语不好,所以很难理解我的单词

我一直在想如何用位运算符解数独。 第一个想法是声明一个三维数组,添加九个适合9-9的数字,并排除与任何坐标对应的行、列和框的数量。 然而,我认为使用位运算符可以进一步降低执行速度

例如,如果数独的一列中的数字是1,我认为它是2的双平方。这相当于0000 0000 0010。 接下来,4将被宣布为16,2的第四个正方形。 这相当于0000 0001 0000

让我们假设所有以这种方式提供的数独都被转换成二进制。 例如,如果第一行是1,2,5/0,8,4/9,3,7,如果使用“或”(|)运算符,则可能会出现以下情况。0011 1011 1110. 对该号码使用'not'(~)运算符将保存以下号码。 1100 0100 0001. 这表明空白中的零点数是六。 问题是有多个空空间,在本例中,我选择输入较低的值,然后转到下一个空空间。 如果你再也放不下了,你可以使用回溯回到前面

#include<stdio.h>
int map[9][9];  //2-Dimensional array to store Sudoku
int line[9];
int row[9];
int box[9];


int solve(int(*map)[9])
{
    int i, j;
    for (i = 0; i<9; i++)
        for (j = 0; j < 9; j++)
        {
            line[i] |= map[i][j];
            row[j] |= map[i][j];
            box[(j / 3) + 3 * (i / 3)] |= map[i][j];
        }
}

int solve1(int(*map)[9])
{
    short i = 0, j = 0;
    int num, num1, num2;
    for (i = 0; i < 9; i++)
    {
        for (j = 0; j < 9; j++)
        {
            if (map[i][j] == 0) //If the cell is empty
            {
                num = (~(line[i] | row[j] | box[(j / 3) + 3 * (i / 3)]));   //Use 'not' operator to find that number
                for (num1 = 1; num1 <= 9; num1++)
                {
                    num2 = 1<<num1;
                    if (num2&num)   //If and operator were used and not 0, it would be one of the numbers that could fit into the space.
                    {           printf("%d %d %d    ", i, j, num2);
                        map[i][j] = num2;
                        line[i] |= num2;
                        row[j] |= num2;
                        box[(j / 3) + 3 * (i / 3)] |= num2;
                        solve1(map);
                    }
                }
                return;     //backtracking
            }
        }
    }
    write(map);
}

int read(int(*map)[9])
{
    int i, j, k, num1;
    FILE*FP1 = fopen("data.txt", "r");  //Read the Sudoku saved in data.txt using the pointer.
    for (i = 0; i < 9; i++)
        for (j = 0; j < 9; j++)
        {
            fscanf(FP1, "%d", &map[i][j]);
            num1 = map[i][j];
            if (map[i][j] != 0)     
            {
                map[i][j] = 1;
                map[i][j] = map[i][j] << num1;  //Converts decimal to binary
            }
        }
    fclose(FP1);
}

int write(int(*map)[9])
{
    int i, j, idx;
    FILE*FP2 = fopen("result.txt", "a");
    for (i = 0; i < 9; i++)
    {
        for (j = 0; j < 9; j++)
        {
            idx = 0;
            while (map[i][j] != 1)    //Converts binary to decimal
            {
                map[i][j] = map[i][j] >> 1;
                idx++;
            }
            fprintf(FP2, "%d ", idx);
        }
        fprintf(FP2, "\n");
    }
    fclose(FP2);
}

int main(void)
{
    read(map);
    solve(map);
    solve1(map);
    return 0;
}
执行回溯时,将返回二维数组中的数字,但不会返回行/列/框中使用的'or'运算符,留下垃圾箱的值

如果在执行回溯时上述三个数组一起工作,则可以解决问题

有什么办法解决这个问题吗


正如我前面所说,您可能不容易看到,因为我不熟悉英语,但感谢您阅读。

如果我理解得很好,您希望在递归调用
solve1
后撤消
=“code>操作吗

您可以在
int
中使用按位和
&
将特定位设置为0:

int value; // value to modify
int bitIndex = 3; // Index of the bit to set to 0 (index starts from 0)

int mask = ~(1 << bitIndex); // All bits set to 1, except the one at bitIndex
value &= mask;

我认为使用位运算符可以进一步降低执行速度。我猜你的意思是“减少执行时间”或“提高执行速度”。(因此,可能没有必要提及位操作很可能是最快的可用操作之一。)我理解你的意思。我还尝试使用xor运算符从位中删除1。但是我不知道把代码放在哪里。@Kremlin你需要知道对
solve1
的递归调用是否能够成功地填充整个网格。根据这一点,您应该回溯(返回您刚刚找到的解决方案),或者撤销您刚刚尝试的号码(尝试其他方法)。
int value; // value to modify
int bitIndex = 3; // Index of the bit to set to 0 (index starts from 0)

int mask = ~(1 << bitIndex); // All bits set to 1, except the one at bitIndex
value &= mask;
line[i] |= num2; // set some bits to 1
line[i] &= ~num2; // set the same bits to 0