本地函数调用与直接写入main

各位老大哥,我在写机试测试题的时候遇到一个问题,同样一段逻辑和代码,使用本地函数调用时运行返回值为Wrong Answer,当把调用的函数直接写入main内后得到的是正确的返回值Accepted,我不太理解这两者之间的区别,请问是否有人可以帮忙解惑。以下是问题以及两份代码
华强种瓜
描述:
华强买到了不保熟的瓜,他很生气,遂决定……自己种瓜!
第二天,华强承包了一大片瓜田,他买来了 n2个保熟的西瓜种子,并且严格按照一个 n×n 米间距的网格进行种植。为了方便华强记忆,这个网格的坐标从 1 开始编号,到 n结束。为了让瓜保熟,他又买来了 k个洒水器,洒水器工作半径为 r米,安装在在网格中的某些种子的正上方。安装完这些洒水器后,华强很想知道现在他的瓜里面有多少能够被撒到水。
输入:
输入共包含 n+k行。第一行包含 3个整数 n、k 和 r,分别表示网格边距、洒水器数量和洒水器工作半径,题目保证 1≤n,k≤200。接下来 k行,每行两个整数 x 和 y,表示每个洒水器在网格中的坐标 (x,y)。
输出:
一行一个整数,表示被洒水器覆盖到的西瓜总数。
样例输入:
5 2 1
3 3
4 2
样例输出:
8
注释:
对于第一组样例,(3,3)上的洒水器工作半径可以覆盖到 (3,3) (4,3) (2,3) (3,2) (3,4) 的瓜。而 (4,2) 上的洒水器可以覆盖到 (4,2) (5,2) (3,2) (4,1) (4,3) 的瓜。去重后,共有 8 个瓜被覆盖到。
这是不通过的

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
const int MAXSIZE = 201;

int arr[MAXSIZE][MAXSIZE];
int sign[MAXSIZE][2];

void Cover (int n,int k, int r) {
    for (int s = 0; s < k; s++){
        for (int i = 0; i <= r; i++){
            for (int j = 0; j <= r; j++){
                if ((float)sqrt((float)pow((float)i, 2) + (float)pow((float)j, 2)) <= r){
                        if (sign[s][0] - i >= 1 && sign[s][1] - j >= 1)
                        arr[sign[s][0] - i][sign[s][1] - j] = true;
                    if (sign[s][0] - i >= 1 && sign[s][1] + j <= n)
                        arr[sign[s][0] - i][sign[s][1] + j] = true;
                    if (sign[s][0] + i <= n && sign[s][1] - j >= 1)
                        arr[sign[s][0] + i][sign[s][1] - j] = true;
                    if (sign[s][0] + i <= n && sign[s][1] + j <= n)
                        arr[sign[s][0] + i][sign[s][1] + j] = true;
                }
            }
        }
    }
}

int main () {
    int n, k, r;
    while (cin >> n >> k >> r){
        memset(arr, false, sizeof(arr));
        for (int i = 0; i < k; i++){
            scanf("%d%d", &sign[i][0], &sign[i][1]);
            arr[sign[i][0]][sign[i][1]] = true;
        }
        Cover(n,k, r);
        int num = 0;
        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= n; j++){
                if(arr[i][j])
                    num++;
            }
        }
        cout << num << endl;
    }
    return 0;
}

这是通过的

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
const int MAXSIZE = 201;

int arr[MAXSIZE][MAXSIZE];
int sign[MAXSIZE][2];

int main () {
    int n, k, r;
    while (cin >> n >> k >> r){
        memset(arr, false, sizeof(arr));
        for (int i = 0; i < k; i++){
            scanf("%d%d", &sign[i][0], &sign[i][1]);
            arr[sign[i][0]][sign[i][1]] = true;
        }
        for (int s = 0; s < k; s++){
            for (int i = 0; i <= r; i++){
                for (int j = 0; j <= r; j++){
                    if ((float)sqrt((float)pow((float)i, 2) + (float)pow((float)j, 2)) <= r){
                            if (sign[s][0] - i >= 1 && sign[s][1] - j >= 1)
                            arr[sign[s][0] - i][sign[s][1] - j] = true;
                        if (sign[s][0] - i >= 1 && sign[s][1] + j <= n)
                            arr[sign[s][0] - i][sign[s][1] + j] = true;
                        if (sign[s][0] + i <= n && sign[s][1] - j >= 1)
                            arr[sign[s][0] + i][sign[s][1] - j] = true;
                        if (sign[s][0] + i <= n && sign[s][1] + j <= n)
                            arr[sign[s][0] + i][sign[s][1] + j] = true;
                    }
                }
            }
        }
        int num = 0;
        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= n; j++){
                if(arr[i][j])
                    num++;
            }
        }
        cout << num << endl;
    }
    return 0;
}

参考GPT和自己的思路:

这个问题的关键在于变量的作用域。

第一个代码中,Cover函数是在main函数之外定义的,调用这个函数时需要将函数的参数传递进去。在函数内部,需要访问一些全局变量,比如arrsign。此时需要用到全局变量,而不是在函数内重新定义。

第二个代码中,将Cover函数的代码直接复制到了main函数中,这样就不需要传参数进去,而且也不需要访问全局变量。所以就不需要将变量作为全局变量。在main函数内部重新定义就可以了。

如果在Cover函数中定义变量,这些变量的作用域仅限于函数内部。比如,int i,j,s变量应当定义在Cover函数内,这样就不会和main函数中的同名变量发生冲突。

总之,要注意变量的作用域。在函数内部定义的变量仅供该函数内部使用,而全局变量则可供所有函数使用。

参考GPT和自己的思路:

问题分析:

通过比较两份代码,我们可以发现不同的地方在于 Cover 函数的位置。在第一份代码中, Cover 函数被定义在 main 函数的外部,并被调用。而在第二份代码中, Cover 函数的所有实现被放在了 main 函数内部。因此,两者最大的区别在于变量的作用域和生命周期。在第一份代码中, Cover 函数定义在 main 函数外部,因此它的变量、参数等的生命周期更长,也更容易受到外部变量的影响。而在第二份代码中, Cover 函数定义在 main 函数内部,因此它更加独立,也更容易保证变量的正确性。

可能的解释:

根据上面的分析,我们可以猜测这个问题的解决方案。首先,我们需要判断哪些变量的作用域和生命周期是有问题的,然后考虑如何解决这些问题。在这个例子中,我们可以看到两个数组变量 arrsign。由于它们的作用域和生命周期对程序的正确性非常重要,我们需要格外关注它们。通过修改代码,我们可以将 Cover 函数中的 arrsign 变量声明成参数传递给函数,这样可以保证这些变量的正确性。

解决方案:

void Cover (int n, int k, int r, int sign[MAXSIZE][2], int arr[MAXSIZE][MAXSIZE]) {
    for (int s = 0; s < k; s++){
        for (int i = 0; i <= r; i++){
            for (int j = 0; j <= r; j++){
                if ((float)sqrt((float)pow((float)i, 2) + (float)pow((float)j, 2)) <= r){
                        if (sign[s][0] - i >= 1 && sign[s][1] - j >= 1)
                        arr[sign[s][0] - i][sign[s][1] - j] = true;
                    if (sign[s][0] - i >= 1 && sign[s][1] + j <= n)
                        arr[sign[s][0] - i][sign[s][1] + j] = true;
                    if (sign[s][0] + i <= n && sign[s][1] - j >= 1)
                        arr[sign[s][0] + i][sign[s][1] - j] = true;
                    if (sign[s][0] + i <= n && sign[s][1] + j <= n)
                        arr[sign[s][0] + i][sign[s][1] + j] = true;
                }
            }
        }
    }
}

int main () {
    int n, k, r;
    while (cin >> n >> k >> r){
        int arr[MAXSIZE][MAXSIZE];
        int sign[MAXSIZE][2];
        memset(arr, false, sizeof(arr));
        for (int i = 0; i < k; i++){
            scanf("%d%d", &sign[i][0], &sign[i][1]);
            arr[sign[i][0]][sign[i][1]] = true;
        }
        Cover(n, k, r, sign, arr);
        int num = 0;
        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= n; j++){
                if(arr[i][j])
                    num++;
            }
        }
        cout << num << endl;
    }
    return 0;
}

在这个版本的代码中,我们将 Cover 函数的 arrsign 参数传递给函数,并在函数体内使用它们。通过这个修改,我们消除了变量的作用域和生命周期问题,使程序更加健壮。