C++帮忙解释一下代码的思想。。。
ProblemDescription猪最近迷上了做幻方,猪还是个中高手,只要你说个奇数N,他就能把N*N的幻方做出来。其实你可以比他做得更好的。猪总是画得很乱,而你可以利...
Problem Description猪最近迷上了做幻方,猪还是个中高手,只要你说个奇数N,他就能把N*N的幻方做出来。其实你可以比他做得更好的。猪总是画得很乱,而你可以利用程序排得很整齐^_^ 幻方的要求:每一行,每一列,还有两条斜线上数字的和都相等。 Input每行有一个数N(0< N < 30),输入0结束。 Output输入一个奇数,输出一个幻方,每个数占3格,顺序参照样板输出,输出完以后加一个回车。 Sample Input5
1
0
Sample Output11 18 25 2 9
10 12 19 21 3
4 6 13 20 22
23 5 7 14 16
17 24 1 8 15
1代码如下#include <stdio.h>
#include <string.h>
int f[30][30];int main()
{
int n;
while(scanf("%d",&n)&&n)
{
memset(f,0,sizeof(f));
int i,j,t=1,k,m;
i=n;
j=(n+1)/2;
f[i][j]=1;
for(t=2; t<=n*n; t++)
{
k=i,m=j;
i++;
j++;
if(i>n && j>n) i=1,j=1;
else if(i>n) i=1;
else if(j>n) j=1;
if(f[i][j]) i=k-1,j=m;
f[i][j]=t;
}
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
printf("%3d",f[i][j]);
puts("");
}
puts("");
} return 0;
} 展开
1
0
Sample Output11 18 25 2 9
10 12 19 21 3
4 6 13 20 22
23 5 7 14 16
17 24 1 8 15
1代码如下#include <stdio.h>
#include <string.h>
int f[30][30];int main()
{
int n;
while(scanf("%d",&n)&&n)
{
memset(f,0,sizeof(f));
int i,j,t=1,k,m;
i=n;
j=(n+1)/2;
f[i][j]=1;
for(t=2; t<=n*n; t++)
{
k=i,m=j;
i++;
j++;
if(i>n && j>n) i=1,j=1;
else if(i>n) i=1;
else if(j>n) j=1;
if(f[i][j]) i=k-1,j=m;
f[i][j]=t;
}
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
printf("%3d",f[i][j]);
puts("");
}
puts("");
} return 0;
} 展开
2个回答
展开全部
幻方又叫魔方
在这里我先来说说奇数幻方的特征:
1。1的位置可以在第一行中间位置 或 最后一行的中间位置
2。N*N幻方所填的数是从1 到 N*N
3。当幻方确定填写1的位置后,接下来的2(即下一个数)的位置在1的位置的右下方
如果有越界情况回到第一行或第一列,如你上面样例中的2的位置是(1,4)(第1行,第4列)
而1的位置是(5,3) 右下的位置应该是(6,3),由于6超过了最大行数5,那么置为1,
即为(1,4)(其实就是一个循环)。同理3的位置就是 (1+1,4+1) 即(2,5)。
接下来是4的位置就是(3,1) ,5的位置是(4,2)。再接下来是6的位置 ,应该是(5,3)
但这里1已经占用来了这个位置,所以从这个数的右下改成正上方 及6的位置为(4-1,2)即
(3,2)。按此规则不断循环,直到将所有的数填完为止。
接下来分析你给的程序的思想。我仅分析核心的填数的思想,剩下的输入输出将不予讨论:
i=n;
j=(n+1)/2;
f[i][j]=1;
for(t=2; t<=n*n; t++)
{
k=i,m=j;
i++;
j++;
if(i>n && j>n) i=1,j=1;
else if(i>n) i=1;
else if(j>n) j=1;
if(f[i][j]) i=k-1,j=m;
f[i][j]=t;
}
以上为核心代码:
i=n;
j=(n+1)/2;
f[i][j]=1;
这几句是将初始位置1填到最后一行的中间
for(t=2; t<=n*n; t++)
循环,将剩下的2到n*n的所有数填入。
k=i,m=j;//保存当前位置,因为后面如果出现已占用情况还要用到这个坐标的正上方
i++;
j++;
默认先寻找当前位置的右下方
if(i>n && j>n) i=1,j=1;
else if(i>n) i=1;
else if(j>n) j=1;
如果出现越界情况 那么把越界情况的那一维置为1
if(f[i][j]) i=k-1,j=m;//是否已占用,如果占用就用保存的当前位置的正上方,注意初始化的memset(f,0,sizeof(f));,0表示未填数,非0表示已有数填入
f[i][j]=t;//在最终确定下来的位置填入数,然后t++ 继续填下一个数,同时 i, j 保存着当前已填的位置
这样循环完后便将所有数填入
幻方的特征满足 行 列 斜线 和 相等的条件。
在这里我先来说说奇数幻方的特征:
1。1的位置可以在第一行中间位置 或 最后一行的中间位置
2。N*N幻方所填的数是从1 到 N*N
3。当幻方确定填写1的位置后,接下来的2(即下一个数)的位置在1的位置的右下方
如果有越界情况回到第一行或第一列,如你上面样例中的2的位置是(1,4)(第1行,第4列)
而1的位置是(5,3) 右下的位置应该是(6,3),由于6超过了最大行数5,那么置为1,
即为(1,4)(其实就是一个循环)。同理3的位置就是 (1+1,4+1) 即(2,5)。
接下来是4的位置就是(3,1) ,5的位置是(4,2)。再接下来是6的位置 ,应该是(5,3)
但这里1已经占用来了这个位置,所以从这个数的右下改成正上方 及6的位置为(4-1,2)即
(3,2)。按此规则不断循环,直到将所有的数填完为止。
接下来分析你给的程序的思想。我仅分析核心的填数的思想,剩下的输入输出将不予讨论:
i=n;
j=(n+1)/2;
f[i][j]=1;
for(t=2; t<=n*n; t++)
{
k=i,m=j;
i++;
j++;
if(i>n && j>n) i=1,j=1;
else if(i>n) i=1;
else if(j>n) j=1;
if(f[i][j]) i=k-1,j=m;
f[i][j]=t;
}
以上为核心代码:
i=n;
j=(n+1)/2;
f[i][j]=1;
这几句是将初始位置1填到最后一行的中间
for(t=2; t<=n*n; t++)
循环,将剩下的2到n*n的所有数填入。
k=i,m=j;//保存当前位置,因为后面如果出现已占用情况还要用到这个坐标的正上方
i++;
j++;
默认先寻找当前位置的右下方
if(i>n && j>n) i=1,j=1;
else if(i>n) i=1;
else if(j>n) j=1;
如果出现越界情况 那么把越界情况的那一维置为1
if(f[i][j]) i=k-1,j=m;//是否已占用,如果占用就用保存的当前位置的正上方,注意初始化的memset(f,0,sizeof(f));,0表示未填数,非0表示已有数填入
f[i][j]=t;//在最终确定下来的位置填入数,然后t++ 继续填下一个数,同时 i, j 保存着当前已填的位置
这样循环完后便将所有数填入
幻方的特征满足 行 列 斜线 和 相等的条件。
展开全部
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询