C语言问题!!!

输出一个"魔方阵".所谓方阵是指这样的方阵.第的每一行,每一列和对角线之和均相等。例如,三阶魔方阵为:
8 1 6
3 5 7
4 9 2
要求输出1~~N的自然数构成的方阵。

现在请求那位高手能帮我解答和解释一下为什么要那样做

粗略地用C++写了个,因为用C个人感觉实在太麻烦:

#include <iostream>
#include <valarray>
#include <algorithm>
#include <cstddef>
#include <deque>
#include <cmath>
#include <iomanip>
using namespace std;

// 打印函数
template<class T>
void print(valarray<T>& t);

// 判定函数
template<class T>
bool judge(valarray<T>& data);

int main()
{
// 这里表示数字从1~9的魔方,一般写1,4,9,16...才能构成正方形
const size_t N = 9;
deque<size_t> data;

for(size_t i = 1; i <= N; ++i)
{
data.push_back(i);
}
valarray<size_t> valdata(data.size());

size_t count = 0;
while(next_permutation(data.begin(), data.end()))
{

for(size_t i = 0; i < valdata.size(); ++i)
valdata[i] = data[i];
if(judge(valdata))
{
++count;
cout << "魔方" << count << " : " << endl;
print(valdata);
}
}
}

template<class T>
void print(valarray<T>& t)
{
const size_t length = sqrt(static_cast<double>(t.size()));
for(size_t i = 0; i < t.size(); ++i)
{
if(i%length == 0)
cout << endl;
cout << setw(3) << t[i];
}
cout << endl;
}

template<class T>
bool judge(valarray<T>& data)
{
valarray<size_t> test(data), plus_unit;

// 魔方边长
const size_t length = sqrt((double)data.size());

// 加和单位,包括横、纵、斜
plus_unit = test[slice(0,length,1)];

// 每个加和单位的总和
const size_t unit_sum = plus_unit.sum();

// 横排检验
for(size_t row = 0; row < length; ++row)
{
plus_unit = test[slice(row*length,length,1)];
if(plus_unit.sum() != unit_sum)
{
return false;
}
}

// 竖排检验
for(size_t col = 0; col < length; ++col)
{
plus_unit = test[slice(col,length,length)];
if(plus_unit.sum() != unit_sum)
{
return false;
}
}

// 对角线1
plus_unit = test[slice(0,length,length+1)];
if(plus_unit.sum() != unit_sum)
{
return false;
}

// 对角线2
plus_unit = test[slice(length-1,length,length-1)];
if(plus_unit.sum() != unit_sum)
{
return false;
}

return true;
}

以下是3×3的正方形的测试结果:

魔方1 :

2 7 6
9 5 1
4 3 8
魔方2 :

2 9 4
7 5 3
6 1 8
魔方3 :

4 3 8
9 5 1
2 7 6
魔方4 :

4 9 2
3 5 7
8 1 6
魔方5 :

6 1 8
7 5 3
2 9 4
魔方6 :

6 7 2
1 5 9
8 3 4
魔方7 :

8 1 6
3 5 7
4 9 2
魔方8 :

8 3 4
1 5 9
6 7 2
请按任意键继续. . .

告戒一句,不要想去找出大于边为3的正方形的其他魔方(比如:16,25,36...),比如3×3的正方形由1~9这9个数成,所以由1到9组成的不同排列就有:

9! = 362880种;

而4×4的正方形由数字1~16组成却有惊人的:

16! = 20922789888000种!

所以你如果试图把const size_t N = 9;改为const size_t N = 16;的话,估计你可能要开着机器算几个月(排除你有超级电脑的例外)。

我设计的这种算法太劣,4楼的那个叶子里的其实才是最理想的效果......
温馨提示:内容为网友见解,仅供参考
第1个回答  2007-03-05
你的题目问的有些含糊不清,是不是有些问题,能不能补充一下?
第2个回答  2007-03-05
你忘记了说明“魔方阵”最重要的特征,即其中每个元素均不相等。否则零矩阵岂不也成“魔方阵”了?
第3个回答  2007-03-05
...而且是连续的9个数字。。。
汗。。想了会。。发现死很多脑细胞都不一定能想出来。也就没机会拿着分了。呵呵。。顶下。。来个高手给看看。。我也想知道答案。。
第4个回答  2007-03-06
我以前写过这个代码,现在不知道扔那了。

下面是用PHP写的,用C写的那个找不到了。
http://xilou.13.hezu1.com/tools/heluo.htm
第5个回答  2007-03-06
程序好像不对哦。。。

C语言的问题!
5,最后一步是,当程序以混合语言编写的程序链接时,在FORTRAN库之前指定C库。重新解决了秋天的飞行问题。

c语言符号问题这里的!()是什么意思
!是单目运算符,即逻辑运算中的 非。括号内(i%a)是取余运算,然后对运算结果取非。C语言中,一般默认运算结果为0是 是逻辑假,运算结果为非0时,是逻辑真,在这里,若i%a的取余结果为0,即逻辑假,那么!(i%a)即为逻辑真,然后执行if(){}内的语句。

c语言排列组合问题
只要C的上面是0,不管下面是什么都等于1。分子是从5开始递减的两个数字相乘,即5*4;分母为从1开始递增的两个数字,即1*2;所以结果为5*4÷(1*2)=10;同理:c53=5*4*3÷(1*2*3)=10 c54=5*4*3*2÷(1*2*3*4)=5 从n个不同元素中,任取m(m≤n,m与n均为自然数,下同)个...

求助C语言中关于“!”的问题
n!是求N的阶乘。就是1*2*3*4...*N“!”就两个意思,一个是非的意思,一个是阶乘的意思,不知你说的是哪个?全句是什么,我没有那本书。

C语言题目!!
C选项:char ch[3]="abc";\/\/这是字符串赋值语句,在B中也说了,字符串必须0结尾,但是空间只有3,放入了abc再放不下0了,空间不够,编译就不会通过,所以错了,char ch[4]="abc";就没问题。D选项:char ch[4];ch="abc";\/\/ch空间够了,但是这是2条语句,char ch[4];已经开辟了空间,...

求c语言一些常见问题,
在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写 if (a=3) then …但C语言中,“=”是赋值运算符,“==”是关系运算符。如:if (a==3) a=b;前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。5....

C语言问题!!!
4、x<y?y:x++的计算方式为,先判断x<y是否为真,如果真,则整个表达式的值为y,否则为x++。在这个问题中,由于x<y为假,所以整个表达式的值为x++,所以结果为5,道理和上个题目一样。(如果把它改成x<y?y:++x的话,则结果为6,因为++x是先使x的值增1,然后再将增加后的x的值作为++x...

c语言 !问题
for(;(c=getchar())!='\\n';)少一个左( 号,从键盘上输入一个字符,判断是不是回车!

C语言问题!!!
main(){ int i,j;for(i=0;i<6;i++) \/*控制输出行,共6行*\/ { for(j=0;ji;j--) \/*控制每行的*号数*\/ printf("*");printf("\\n"); \/*每行后换行*\/ } } 2. .#include "stdio.h"main(){ int i,j;for(i=0;i<6;i++) \/*控制输出行,共6行*\/ { for(j...

c语言程序设计问题
答:一个一个来:先看i:i=15; m=(i++)+(i++)+(i++); 可以化解为: m=i+i+i; i++; i++; i++;从左至右执行。这是c语音的执行顺序。得 m=45;在看j:j=20; n=(--j)+(--j)+(--j);可以化解为:看计算机先后执行顺序:先算第一个--j,再算第二个--j,在...

相似回答