当前位置: 首页 > 知识库问答 >
问题:

谷歌Kickstart 2013年B轮问题数独检查器给出了错误的答案,但它正在工作

马华茂
2023-03-14

https://codingcompetitions.withgoogle.com/kickstart/round/0000000000434ad7/00000000004347b3
数独是一种流行的单人游戏。目标是用数字填充9x9矩阵,以便每列、每行和所有9个不重叠的3x3子矩阵包含从1到9的所有数字。每个9x9矩阵在游戏开始时部分完成,通常有一个独特的解决方案
给定一个完整的N2xN2数独矩阵,您的任务是确定它是否是有效的解决方案。有效的解决方案必须满足以下标准:

每行包含从1到N2的每个数字,每行一次
每列包含从1到N2的每个数字,每列一次
将N2xN2矩阵划分为N2个不重叠的NxN子矩阵。每个子矩阵包含从1到N2的每个数字,每个数字一次

我的代码:

 #include <iostream>
 using namespace std;


 int main()
{
int i, j, k, no, n, sum, t[36][36], validsum;
cin >> no;
for (k = 0; k < no; k++)
{
    cin >> n;

    for (i = 0; i < n * n; i++)
    {
        for (j = 0; j < n * n; j++)
        {
            cin >> t[i][j];
        }
    }

    bool valid = 1;
    
    validsum = ((n*n)*(n*n+1))/2;
    sum = 0;

    if (valid == 1)
    {
        for (i = 0; (i < n * n) && valid == 1; i++)
        {
            sum = 0;
            for (j = 0; (j < n * n) && sum < validsum; j = j+1) {
                sum += t[i][j];
            }
            if (sum != validsum)
                valid = 0;
        }
    }

    if (valid == 1)
    {
        for (j = 0; j < n * n && valid == 1; j++)
        {
            sum = 0;
            for (i = 0; i < n * n && sum < validsum; i++)
            {
                sum += t[i][j];
            }
            if (sum != validsum)
                valid = 0;
        }
    }

    cout << "Case #" << k + 1 << ": ";
    if (valid == 1)
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
}
}

我的结果是:

Case #1: Yes
Case #2: No
Case #3: No

示例结果:

Case #1: Yes
Case #2: No
Case #3: No

是因为速度不够快吗?

共有2个答案

裴劲
2023-03-14

在某些情况下,代码不会返回正确答案。你也必须检查子矩阵,不能用求和来检查。下面是三个测试用例来演示代码中的问题:

3
3
5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5
3
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
8 5 9 7 6 1 4 2 3
1 9 8 3 4 2 5 6 7
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9
3
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
2 8 8 3 4 2 5 6 7
7 6 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9

在这两种情况下,代码都返回Yes,但在这两种情况下,预期结果都是No

魏雅惠
2023-03-14

正如@jabaa提到的,你忘了检查子矩阵。

此外,检查总和是不够的,例如1 3 = 2 2

一个有效的解决方案是,在每一行、每一列或每一个子矩阵中,检查没有数字出现两次。

这是有效的,条件是首先检查所有数字是否在良好的范围内[1, n^2]

#include <iostream>
#include <vector>

bool check_line (int sudo[36][36], const int &n, const int &n2, const int &line) {
    std::vector<int> vali(n2 + 1, 0);
    for (int i = 0; i < n2; i++) {
        int num = sudo [line][i];
        if (vali[num]) return false;
        vali[num] = 1;
    }
    return true;
}

bool check_col (int sudo[36][36], const int &n, const int &n2, const int &col) {
    std::vector<int> vali(n2 + 1, 0);
    for (int i = 0; i < n2; i++) {
        int num = sudo [i][col];
        if (vali[num]) return false;
        vali[num] = 1;
    }
    return true;
}

//  line and col represent the position of the first cell of the submatrix
bool check_sub_matr (int sudo[36][36], const int &n, const int &n2, const int &line, const int &col) {
    std::vector<int> vali(n2 + 1, 0);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            int num = sudo [line+i][col+j];
            if (vali[num]) return false;
            vali[num] = 1;
        }
    }
    return true;
}

bool validity (int sudo[36][36], const int& n, const int& n2) {
    // First check validity of numbers
    for (int i = 0; i < n2; i++) {
        for (int j = 0; j < n2; j++) {
            int number = sudo[i][j];
            if ((number < 1) || (number > n2)) return false;
        }
    }
    // Check lines
    for (int i = 0; i < n2; i++) {
        auto check = check_line (sudo, n, n2, i);
        if (!check) return false;
    }
    // Check columns
    for (int i = 0; i < n2; i++) {
        auto check = check_col (sudo, n, n2, i);
        if (!check) return false;
    }
    // Check sub-matrices
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; ++j) {
            auto check = check_sub_matr (sudo, n, n2, i*n, j*n);
            if (!check) return false;
        }
    }   
    return true;
}

int main() {
    int sudo[36][36];
    int nt;
    std::cin >> nt;
    
    for (int t = 1; t <= nt; ++t) {
        int n, n2;
        std::cin >> n;
        n2 = n*n;
        for (int i = 0; i < n2; i++) {
            for (int j = 0; j < n2; j++) {
                std::cin >> sudo[i][j];
            }
        }
        auto valid = validity (sudo, n, n2);
        std::cout << "Case #" << t << ": ";
        if (valid) std::cout << "Yes" << std::endl;
        else std::cout << "No" << std::endl;
    }
    return 0;
}
 类似资料:
  • 问题内容: 我计算出以下内容: 即使执行10.0-9.2也可以得到上述结果。为什么多余的7会出现在结果中? 我在python 3.2上。 问题答案: 浮点算法基于数字的二进制近似,因此存在一些内置问题。 有一个很好的解释在Python文档。 如果您需要更准确的答案,则可以签出该模块。

  • 我使用下面的代码来格式化日期。但是当我以不正确的格式给出数据时,它会给出意想不到的结果。 在上述情况下,输出为-formattedVal:0009-02-05。 它不是抛出解析异常,而是解析值并给我一个不正确的输出。有人能帮我理解这种反常的行为吗。

  • 问题内容: 在该问题中,我引用了以下代码: 我在该问题中发现,该结果按model.classes_给出的顺序表示了属于每个类的点的概率 所以…如果正确解释,此答案表示该点可能是“橙色”(由于数据量很少,因此置信度较低)。但是直觉上,这个结果显然是不正确的,因为给出的点与“苹果”的训练数据相同。可以肯定的是,我也进行了相反的测试: 同样,显然是不正确的,但方向相反。 最后,我尝试了更远的点。 同样,

  • 我正在学习DOM,希望创建一个简单的JavaScript with Html测验(用于练习)。现在我遇到的问题是,当我点击提交时,所有的答案都是对的,而不是一个是对的,三个是错的。我认为这是我的html和我将ID分配给不同标签的方式的问题,但我不能弄清楚我做错了什么。 代码 多谢了。

  • 谢谢大家。 我有一个包含7张的谷歌电子表格。我试图将最后一张工作表中的数据从单元格A1: D1移动到附加到同一工作表底部的新行。 下面是我正在使用的代码片段: 在我运行代码后,在标签“薪资检查历史记录”中,在工作表底部的新行中,我得到以下内容:“[Ljava.lang.对象;@3e0d05f9” 有人能告诉我(a)这个错误是什么,(b)这意味着什么,以及(c)我如何修复这个问题或实现我的目标,即“

  • 在Apache J Meter中用1个线程触发请求时,我得到以下错误-org.Apache.http.nohttpresponseException:xxx.tc.at.xxx.net:8443未能在org.Apache.http.impl.conn.defaultthtpresponseparser.parsehead(Defaultthtpresponseparser.java:141)在or