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

时间:2014-08-06 17:13:20

标签: c++

您将获得一个方形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的值。我不明白为什么?有什么方法可以优化它吗?

Test Input File Link

不适用于上述输入。

PS:这不是一个家庭作业问题。我无法猜测如何解决它。

3 个答案:

答案 0 :(得分:0)

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

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';
}

答案 1 :(得分:0)

代码中的一些问题:

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

一些改进:

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

代码(使用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;
}

答案 2 :(得分:0)

定义两个阵列是一个坏主意,其中一个阵列具有元素&#39;输入int。

这是一个满足您的任务条件的简单解决方案 程序逐行读取输入。首先,它使用地图大小的数字读取第一行,并将其转换为size_t类型的对象。 然后用字符&#39; 0&#39;初始化大小为n * n的地图。默认情况下。

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

Adter它使用数字读取每一行并使用标准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个字符并将其复制到行中。

事实上,在完成任务之后。您所需要的只是比较地图内的每个元素,使其大于调整后的元素。

#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