堆栈溢出错误强制一个魔方。任何可能的解决方

时间:2013-05-07 12:52:51

标签: c stack-overflow backtracking magic-square

这是我的问题,对于练习我需要通过回溯来强制它来生成魔方

我认为将矩阵分配为向量和更改坐标的函数可能很有用。你可以想象,即使使用3x3魔方,它也会给我一个堆栈溢出问题。

调试它我发现它或多或少发生在生成的一半,更确切地说是函数chk_magic(int *m, int n)调用change_coord(i, j, m, n);的地方。

这是整个代码,我在那里签署了中断程序的行。

#include <stdio.h>
#include <stdlib.h>

int chk_magic(int*, int);
void generate_magic(int*, int, int);
int change_coord(int, int, int*, int);

int back_f;

int main()
{
    int i, j, n=3, *m;
    //printf("Inserisci la dimensione del quadrato: ");
    //scanf("%d", &n);

    m=malloc(n*n*sizeof(int*));
    for(i=0; i<(n*n); i++)
    {
        m[i]=1;
    }
    printf("Generazione in corso (se la dimensione e' maggiore di 4 potrebbero volerci minuti)...\n");
    generate_magic(m, n, n*n-1);
    for(i=0; i<n; i++)
    {
        for(j=0; j<n; j++)
        {
            printf("%3d ", change_coord(i, j, m, n));
        }
        printf("\n");
    }

    return 0;
}

int chk_magic(int *m, int n)
{
    int i, j, magic_n, orizzontal_buffer, vertical_buffer, flag;
    flag=0;
    magic_n=n*(n*n + 1)/2;

    for(i=0; i<n; i++)
    {
        orizzontal_buffer=0;
        vertical_buffer=0;

        for(j=0; j<n; j++)
        {
            orizzontal_buffer+=change_coord(i, j, m, n); // <<-- HERE! HALP!
            vertical_buffer+=change_coord(j, i, m, n);
        }
        if(vertical_buffer!=magic_n || orizzontal_buffer!=magic_n)
        {
            flag=1;
            return flag;
        }
    }
    orizzontal_buffer=0;
    vertical_buffer=0;
    for(i=0, j=n-1; i<n; i++, j--)
    {
        orizzontal_buffer=change_coord(i, i, m, n);
        vertical_buffer=change_coord(i, j, m, n);
    }
    if(vertical_buffer!=magic_n || orizzontal_buffer!=magic_n)
        {
            flag=1;
        }

    return flag;
}

void generate_magic(int *m, int n, int pos)
{
    if(m[pos]<n*n)
    {
        m[pos]++;
        back_f=chk_magic(m, n);
        if(back_f==0)
        {
            return;
        }
        generate_magic(m, n, n*n-1);
        return;
    }
    if(m[pos]==n*n)
    {
        if(back_f==0)
        {
            return;
        }
        m[pos]=1;
        generate_magic(m, n, pos-1);
        return;
    }
    if(pos==-1)
    {
        return;
    }
    return;
}

int change_coord(int x, int y, int *m, int dim)
{
    return m[(x*dim)+y];
}

谷歌搜索我发现,对于奇数,有一种算法可以轻松生成它,但问题仍然存在于偶数(此外我的教授希望它与暴力递归)。

任何可能的解决方案?

1 个答案:

答案 0 :(得分:1)

这是家庭作业,所以我不打算修改你的代码......但是我会为你做一些分析来向你展示这个问题。仅供参考:您真的应该学会使用调试器并跟踪代码。


这里最大的问题是你的&#34;递归&#34;逻辑只是在两个街区之间来回反弹,没有&#34;最低的步骤&#34;因此,您使用太多函数调用填充缓冲区并获得堆栈溢出:

void generate_magic(int *m, int n, int pos)
{
    if(m[pos]<n*n)
    {
        m[pos]++;
        back_f=chk_magic(m, n);
        if(back_f==0)
        {
            return;
        }
        generate_magic(m, n, n*n-1);  <--- 'Recursive' step

因此,当您调用此功能时,您有m* == your memory blockn == 3pos == 8(3 * 3-1)。

我把&#34;递归&#34;在引号中,因为您没有执行递减步骤,所以每次使用相同参数一次又一次地调用generate_magic()时,此代码会运行(n始终为3,pos为总是8)

经过几次迭代后,m[pos]将从1增加到9,现在如果检查失败,我们会跳到下一个块:

if(m[pos]==n*n)
{
    if(back_f==0)
    {
        return;
    }
    m[pos]=1;
    generate_magic(m, n, pos-1);  <- 'Recursive' step

所以现在我们将前一个值(9)的代码集m [pos]输回到我们开始的值(1)然后我们执行&#34;递归&#34;步骤,使用值(generate_magic()n==3pos=7)调用m[pos]==1

好的,这次我们重新开始使用不同的值,对吧?我们第一次有:

n == 3pos == 8
现在我们有:
n == 3pos == 7

哎呀,但是当我们第一次点击时会发生什么?递归&#34;再打个电话?

generate_magic(m, n, n*n-1);

那将重置我们的下一个条目:

n == 3pos == 8

这无处不在。迟早所有这些函数/参数推送到堆栈将会杀死我们,因为我们正在进入无限循环。


旁注:

malloc(n*n*sizeof(int*));

您想要sizeof(int),而不是sizeof(int*),因为您在矩阵中标记了int,而不是int的指针。