为什么大的输入会得到错误的答案

Why am I Getting incorrect answer for large inputs

本文关键字:错误 答案 输入 为什么      更新时间:2023-10-16

您将获得一个正方形n×n地图。地图的每个单元格都有一个值,表示相应区域的深度。当且仅当该单元不在地图的边界上并且相邻的每个单元的深度都严格小于该单元时,我们将该单元称为空腔。如果两个单元格有共同的边,则它们相邻。

你需要在地图上找到所有的空腔并用字母x来描绘它们

输入格式

第一行包含一个整数n(1≤n≤100),表示映射的大小。下面的n行每一行包含n个不带空格的正数。数字(1-9)表示相应区域的深度。

输出格式

输出n行,表示结果映射。每个空腔应替换为字符x

示例输入

 4
 1112   
 1912 
 1892
 1234

的示例输出
 1112
 1X12
 18X2
 1234

现在,我编写了这段代码。但是对于较大的值,这是不正确的答案,即n的值为99或100或96。

这基本上是接受输入数字,并将输入数组的每一行分成单独的数字。然后,它将每个数字与下一位和前一位进行比较,以检查它是否大于或小于所考虑的数字。但是,当n的值较大时,它会显示错误的答案。

下面是工作代码。(在样本输入上工作良好)

#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
int main(void) {
    int n, i = 0;
    cin >> n;
    int values[1000];
    int j;
    for (i = 0; i < n; i++) {
        int p;
        cin >> p;
        values[i] = p;
    }
    char digits[1000][1000];
    int foo;
    for (i = 0; i < n; i++) {
        foo = n - 1;
        while (values[i] != 0) {
            digits[i][foo] = values[i] % 10 + 48;
            values[i] = values[i] / 10;
            foo--;
        }
    }
    for (i = 1; i < n - 1; i++) {
        j = 1;
        while (j != n - 1) {
            if (digits[i][j] > digits[i][j - 1] &&
                digits[i][j] > digits[i][j + 1]) {
                digits[i][j] = 'X';
            }
            j++;
        }
    }
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            printf("%c", digits[i][j]);
        }
        printf("n");
    }
    return 0;
}

这显示了输入值较大时的错误答案,例如n的值为96100。我不明白为什么?有什么方法可以优化它吗?

测试输入文件链接

对上述输入无效

PS:这不是家庭作业问题。我猜不出如何解决这个问题。

您只检查两个相邻的单元格。每个单元格有四个相邻的单元格:左、右、上、下。您还需要像这样检查顶部和底部的单元格:

if ( digits[i][j] > digits[i][j-1] && digits[i][j] > digits[i][j+1] && digits[i][j] > digits[i-1][j] && digits[i][j] > digits[i+1][j] )
{
    digits[i][j] = 'X';
}

定义两个数组,其中一个元素的类型为int,这是一个坏主意。

这是一个满足你的任务条件的简单解程序逐行读取输入。首先,它读取带有map大小编号的第一行,并将其转换为size_t类型的对象。然后初始化大小为n * n的映射,默认使用字符'0'。

for ( size_t i = 0; i < n; i++ )
{
    std::memset( map[i], '0', n );
}

使用标准C函数std::memcpy读取每一行数字并将其复制到映射的对应行

for ( size_t i = 0; i < n && std::getline( std::cin, line ); i++ )
{
    line = line.substr( 0, n );
    std::memcpy( map[i], line.c_str(), line.size() );
}

由于输入可能是错误的,并且一行可以包含多于或少于n个字符,因此我们从读取行中提取恰好n个字符,并将它们复制到该行中。

之后赋值就完成了。您所需要做的就是比较map中的每个元素是否大于调整后的元素。

#include <iostream>
#include <string>
#include <cstring>
int main() 
{
    const size_t N = 100;
    char map[N][N];
    std::string line;
    std::getline( std::cin, line );
    size_t n = std::stoul( line );
    if ( N < n ) n = N;
    for ( size_t i = 0; i < n; i++ )
    {
        std::memset( map[i], '0', n );
    }
    for ( size_t i = 0; i < n && std::getline( std::cin, line ); i++ )
    {
        line = line.substr( 0, n );
        std::memcpy( map[i], line.c_str(), line.size() );
    }
    std::cout << n << std::endl;
    for ( size_t i = 0; i < n; i++ )
    {
        for ( size_t j = 0; j < n; j++ ) std::cout << map[i][j] << ' ';
        std::cout << std::endl;
    }
    std::cout << std::endl;
    for ( size_t i = 1; i + 1 < n; i++ )
    {
        for ( size_t j = 1; j + 1 < n; j++ )
        {
            if ( map[i][j-1] < map[i][j] &&
                 map[i][j+1] < map[i][j] &&
                 map[i-1][j] < map[i][j] &&
                 map[i+1][j] < map[i][j] )
            {
                map[i][j] = 'X';
            }
        }
    }
    for ( size_t i = 0; i < n; i++ )
    {
        for ( size_t j = 0; j < n; j++ ) std::cout << map[i][j] << ' ';
        std::cout << std::endl;
    }
    std::cout << std::endl;
    return 0;
}

输出为

4
1 1 1 2 
1 9 1 2 
1 8 9 2 
1 2 3 4 
1 1 1 2 
1 X 1 2 
1 8 X 2 
1 2 3 4 

代码中的一些问题:

  • 在问题中提供的输入内容中,数字是在一个int类型变量表示的范围内,但是提供的链接所引用的文件中数字的内容远远超出了c++中任何整数类型的范围。您需要能够存储多达100位数字。这是你的问题的主要原因,它是每一行的数字。您可以将其视为std::string来解决。
  • 根据问题描述,需要检查上下相邻单元格。
一些改进:

  • 使用std::vector代替C array。不需要浪费未使用的内存(顺便说一下,在问题的声明中,他们说行数将在1到100之间,你可以将valuesdigits变量声明为该长度),向量自动管理它们的内存(在需要时增长),它们检查超出界限的索引等…
  • 使用std::string代替int,(阅读前面的原因)。
  • 使用std::getline逐行读取文件
  • std::string的值可以作为char进行比较,因为它们是数字,并且'0' = 0x30 ..'9' = 0x39,并且数字的相同顺序适用于它们的字符表示。

代码(在c++ 11下测试GCC 4.9.0):

#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
    unsigned int lines;
    std::cin >> lines;
    std::vector<std::string> values;
    values.reserve(lines);
    // Reading the matrix
    std::string line;
    std::getline(std::cin, line); // Reading the rest of the first line
    while (std::getline(std::cin, line)) {
        values.push_back(line);
    }
    // Checking the depths and marking the cavities
    for (unsigned int i = 1; i < values.size() - 1; i++) {
        const auto& actual_number = values[i];
        for (unsigned int j = 1; j < actual_number.size() - 1; j++) {
            if (actual_number[j] > actual_number[j - 1] &&
                actual_number[j] > actual_number[j + 1] &&
                actual_number[j] > values[i - 1][j] &&
                actual_number[j] > values[i + 1][j]) {
                values[i][j] = 'X';
            }
        }
    }
    // Printing output
    for (const auto& n : values) {
        std::cout << n << std::endl;
    }
    return 0;
}

对于大的示例输入文件,输出是相同的数字,因为它们都是9,没有更大的了。

使用提供的代码作为基础的版本:

#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
int main(void) {
    int n, i = 0;
    cin >> n;
    char values[100][100]; // changed the limit
    int j;
    for (i = 0; i < n; i++) {
        cin >> values[i]; // reading the line. 'int p;' not necessary
    }
    // declaration of digits, and initialization not necessary
    for (i = 1; i < n - 1; i++) {
        j = 1;
        while (j != n - 1) {
            if (values[i][j] > values[i][j - 1] &&
                values[i][j] > values[i][j + 1] &&
                values[i][j] > values[i - 1][j] &&
                values[i][j] > values[i + 1][j]) {
                values[i][j] = 'X';
            }
            j++;
        }
    }
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            printf("%c", values[i][j]);
        }
        printf("n");
    }
    return 0;
}