这是我的问题,对于练习我需要通过回溯来强制它来生成魔方。
我认为将矩阵分配为向量和更改坐标的函数可能很有用。你可以想象,即使使用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];
}
谷歌搜索我发现,对于奇数,有一种算法可以轻松生成它,但问题仍然存在于偶数(此外我的教授希望它与暴力递归)。
任何可能的解决方案?
答案 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 block
,n == 3
和pos == 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==3
和pos=7
)调用m[pos]==1
好的,这次我们重新开始使用不同的值,对吧?我们第一次有:
n == 3
和pos == 8
现在我们有:
n == 3
和pos == 7
哎呀,但是当我们第一次点击时会发生什么?递归&#34;再打个电话?
generate_magic(m, n, n*n-1);
那将重置我们的下一个条目:
n == 3
和pos == 8
这无处不在。迟早所有这些函数/参数推送到堆栈将会杀死我们,因为我们正在进入无限循环。
旁注:
malloc(n*n*sizeof(int*));
您想要sizeof(int)
,而不是sizeof(int*)
,因为您在矩阵中标记了int
,而不是int
的指针。