在数独回溯中的TLE

时间:2017-10-24 19:48:28

标签: c++ backtracking sudoku

我已经编写了一个代码来解决使用回溯的9x9数据,它以vector<vector<char> >的形式输入并且有'。'如果缺少数字。当我运行代码时,我得到了一个TLE。我试过找到这个bug但却找不到。请指出错误。 next函数返回要检查的下一个坐标。 safe函数检查在某个位置分配号码是否安全。这是代码:

bool safe(vector<vector<char> > &A, int a, int b, int val)
{
    int N = A.size();

    //check horiz
    int sum;
    int i;
    sum = 0;
    for(i=0;i<N;i++)
    {
        if(A[a][i]=='.')
            break;
        else
            sum+=A[a][i]-'0';
    }
    if(i==N && sum!=(N*(N+1)/2))
        return 0;

    //check vert
    sum = 0;
    for(int i=0;i<N;i++)
    {
        if(A[i][b]=='.')
            break;
        else
            sum+=A[i][b]-'0';
    }

    if(i==N && sum!=(N*(N+1)/2))
        return 0;

    //check box

    int x, y;
    x = a%3;
    y = b%3;

    sum = 0;
    for(int i=x*3;i<x*3 + 3;i++)
    {
        for(int j=y*3;j<y+3;j++)
        {
            if(A[i][j]=='.')
                return 1;
            else
                sum+=A[i][j]-'0';
        }
    }
    if(sum!=(N*(N+1)/2))
        return 0;

}



pair<int, int> next(int a, int b)
{
    int x, y;
    x = a+1;
    y = b;
    if(x==9)
    {
        x=0;
        y++;
    }
    pair<int, int> p = {x, y};
    return p;
}

bool solve(vector<vector<char> > &A, vector<vector<bool> > B, int a, int b)
{
    // cout<<a<<" "<<b<<endl;
    if(b==A.size())
        return 1;

    pair<int, int> p;
    if(B[a][b]==0)
    {
        p = next(a, b);
        return solve(A, B, p.first, p.second);
    }
    else
    {
        for(int i=1;i<=9;i++)
        {
            if(safe(A, a, b ,i))
            {
                A[a][b] = i + '0';
                p = next(a, b);
                if(solve(A, B, p.first, p.second))
                    return 1;
            }
        }
        A[a][b] = '.';
    }
    return 0;
}

void Solution::solveSudoku(vector<vector<char> > &A) {
    vector<bool> tmp(A.size(), 0);
    vector<vector<bool> > B(A.size(), tmp);

    for(int i=0;i<A.size();i++)
    {
        for(int j=0;j<A.size();j++)
        {
            if(A[i][j]!='.')
            {
                B[i][j] = 1;
            }
        }
    }

    solve(A, B, 0, 0);

}

1 个答案:

答案 0 :(得分:0)

代码中有两个主要错误:

  1. addPotholeMarkers()功能错误。

    • 您需要确保行,列和框中没有两个数字相同。您正在计算每行,每列和每个值中的值的总和,如果预期总和则返回。这不起作用。我建议使用位域来跟踪使用的数字。

        

      Ex :1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 = 45 = 9 + 9 + 9 + 9 + 4 + 1 + 1 + 1 + 1 + 1

    • safe没有使用传递给它的值safe,这没关系,只是将其从参数列表中删除。

    • 您应该使用val时使用%

    • 您正在重新定义变量名称,例如,循环中的变量/与您在后续i语句中使用的i不同:< / p>

  2. if
    1. 当递归调用无法找到解决方案时,您需要将for(int i=0;i<N;i++) { if(A[i][b]=='.') break; else sum+=A[i][b]-'0'; } if(i==N && sum!=(N*(N+1)/2)) 重置为A[a][b]。否则,您对'.'的下一次调用将使用之前的状态。

      safe
    2. 你真的不需要布尔的for(int i=1;i<=9;i++) { if(safe(A, a, b ,i)) { A[a][b] = i + '0'; p = next(a, b); if(solve(A, B, p.first, p.second)) return 1; A[a][b] = '.'; //RESET BACK } } 向量。您可以将其删除,然后针对B测试A[a][b]

      我在代码中修复了这些错误,而且速度非常快。它在我的机器上在60毫秒内解决this puzzle