这个贴子是散分贴,来者有分。
接分的同志请注意:请每天只UP一次,如果UP多次,只给UP一次的分。这个贴子以前贴了一次,没有等到结果,现在重新贴一次。希望能够有高手解答
如果能够解答出来的话,另外开给分贴子给分。
http://expert.csdn.net/Expert/topic/1732/1732898.xml?temp=.6524622
什么是魔方阵?
魔方阵是由1至n*n(3  <=  N  <=  9)个数组成方阵的。要求横加、竖加、斜加都相等。
如1 2 3
  4 5 6
  7 8 9组成的魔方阵为:  6 1 8
  7 5 3
  2 9 4
横加、竖加、斜加都相等于15当然,对于奇数阶的魔方阵可以有简便的方法。
(方阵转45度,之后数往里压,然后再交换)。我现在并不想用这种取巧的办法。而是希望算出所有的可能排列之后,把符合魔方阵的排列显示出来,并统计一共有多少种排列方法。我以前编写过魔方阵问题的程序。利用递归。这种方法只能用于3阶,即上图。4阶魔方阵,机器就无法算出结果了。问题1:
有一个思路,可是无法编写出来代码。(100分)
每次两个数字交换位置,通过交换位置来排列出魔方阵的所有可能。
比如第一次是头两个数字交换位置,
第二次是第三个和第一个交换位置,
第三次是第三个和第二个交换位置…
谁能够用把这个思路的代码写出来?请教高手
问题2:如果有更好的算法,能够得到所有的可能的排列,然后从中找出符合魔方阵的方阵来。)100分)。
问题3:如果再有这个算法的代码,加分100。
这个贴子是散分贴,来者有分。
如果能够解决上述三个问题中的一个或多个,我另外开一个给分的贴子送分。
问题4:我下面的三个程序中,有一个用递归的程序中,存在BUG,解决这个BUG的,加分50。以前用递归做出来过。很长时间没用递归了,手都生了。如果自己编写用递归做出来的话,加分50
以下是从以前的贴子中COPY出来的一些内容,也许会对您解答这个问题有所帮助。
小时候,玩魔方阵的时候,找到一个方法。
就是对于所有的魔方阵,都可以用把它的内圈看成一个小魔方阵的方法来解决。
比如说五阶魔方阵,内圈可以看成一个三阶魔方阵,先排好内圈,再排外圈。
七阶魔方阵,可以把内圈看成一个五阶魔方阵。把五阶排好后,再排外圈。
六阶魔方阵,内圈可以看成一个四阶魔方阵。
用这个方法。小时候用手工排列,排出过七阶魔方阵。再高阶的,就排不出来了。有没有算法方面的高手,提供一个思路。可以解决魔方阵的问题。
JennyVenus(项链啊,首饰啊,金银珠宝啊,月光宝盒。) 的程序对于奇数阶的魔方阵都好用。问题是这个算法如何证明它正确。再有,我所说的,如何能够等到所有的排列?(通过数字交换位置,因为我认为数字交换位置应该是找到全排列的比较好的方法。否则的话,程序的计算量将大到现有的台式机无法承受的地步。)
To: maohbao() :上面JennyVenus(项链啊,首饰啊,金银珠宝啊,月光宝盒。) 的程序就是你所说的算法。编写的非常不错,代码简洁,明了。运行速度也很快。问题是,你如何证明它是对的,再有,如何能够得到所有的排列中,有多少种排列方法。对于三阶,有8种,全是一样的,对于五阶,我以前手排,就排出过两种不同的。问题是一共有多少种不同的。
下面给出三个程序
一个是回复人: JennyVenus() (  ) 信誉:151给出的一个比较经典的程序代码。
一个是我新编写的通过递归调用得到魔方阵的方法。有BUG,可以得出部分正确的解。
一个是我编写的最笨的魔方阵算法。
奇数
#include<stdio.h>
#include<conio.h>
#define MAX 2
void main()
{
int arr[MAX+1][MAX+1],val=1,i,j,k;
clrscr();
for(i=0;i<=MAX;i++)
for(j=0;j<=MAX;j++)
arr[i][j]=0;
for(i=0,j=MAX/2,k=0;k<((MAX+1)*(MAX+1));k++)
{
arr[i--][j--]=val++;
if(i<0)
i=MAX;
if(j<0)
j=MAX;
if(arr[i][j]!=0)
{
i=i+2;
j=j+1;
if(i>MAX)
i%=(MAX+1);
if(j>MAX)
j%=(MAX+1);
}
}
for(i=0;i<=MAX;i++)
{
for(j=0;j<=MAX;j++)
printf("%d\t",arr[i][j]);
printf("\n");
}
getch();
}偶数的幻方分为4的倍数和不是4的倍数的两种,4的倍数的可以看《射雕英雄传》,背了歌诀就行了,非4的倍数的不会(原理都忘了),需要扩充。
#include <stdio.h>
#define NUM 3int a[9], result, count;void print()
{
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
printf("%3d", a[i*3+j]);
}
printf("\n");
}
getchar();
}bool IsMagic() // 判断是否为魔方阵
{
int sumx, sumy, sumi[NUM], sumj[NUM];
sumx = sumy = 0;
for(int i = 0; i < NUM; i++)
sumi[i] = sumj[i] = 0;
for(i = 0; i < NUM; i++)
{
for(int j = 0; j < NUM; j++)
{
if(i == j)
sumx += a[i*NUM+j];
if(i == NUM-j-1)
sumy += a[i*NUM+j];
sumi[i] += a[i*NUM+j];
sumj[j] += a[i*NUM+j];
}
}
if(sumx != sumy) return false;
for(i = 0; i < NUM; i++)
{
if(sumi[i] != sumj[i] || sumi[i] != sumx)
return false;
}
return true;
}void main()
{
for(int i1 = 1; i1 < 10; i1++)
{
a[0] = i1;
for(int i2 = 1; i2 < 10; i2++)
{
if(i2 == i1) continue;
a[1] = i2;
for(int i3 = 1; i3 < 10; i3++)
{
if(i3 == i1 || i3 == i2) continue;
a[2] = i3;
for(int i4 = 1; i4 < 10; i4++)
{
if(i4 == i1 || i4 == i2 || i4 == i3) continue;
a[3] = i4;
for(int i5 = 1; i5 < 10; i5++)
{
if(i5 == i1 || i5 == i2 || i5 == i3 || i5 == i4) continue;
a[4] = i5;
for(int i6 = 1; i6 < 10; i6++)
{
if(i6 == i1 || i6 == i2 || i6 == i3 || i6 == i4 || i6 == i5) continue;
a[5] = i6;
for(int i7 = 1; i7 < 10; i7++)
{
if(i7 == i1 || i7 == i2 || i7 == i3 || i7 == i4 || i7 == i5 || i7 == i6) continue;
a[6] = i7;
for(int i8 = 1; i8 < 10; i8++)
{
if(i8 == i1 || i8 == i2 || i8 == i3 || i8 == i4 || i8 == i5 || i8 == i6 || i8 == i7) continue;
a[7] = i8;
for(int i9 = 1; i9 < 10; i9++)
{
if(i9 == i1 || i9 == i2 || i9 == i3 || i9 == i4 || i9 == i5 || i9 == i6 || i9 == i7 || i9 == i8) continue;
a[8] = i9;
{
count++;
if(IsMagic())
{
result++;
print();
}
}
}
}
}
}
}
}
}
}
}
}#include <stdio.h>
#define NUM 3int a[NUM*NUM] = {9, 3, 8, 4, 5, 1, 7, 2, 6};
bool b[NUM*NUM+1];
int last[NUM*NUM], count, result;
int error;bool IsMagic() // 判断是否为魔方阵
{
int sumx, sumy, sumi[NUM], sumj[NUM];
sumx = sumy = 0;
for(int i = 0; i < NUM; i++)
sumi[i] = sumj[i] = 0;
for(i = 0; i < NUM; i++)
{
for(int j = 0; j < NUM; j++)
{
if(i == j)
sumx += a[i*NUM+j];
if(i == NUM-j-1)
sumy += a[i*NUM+j];
sumi[i] += a[i*NUM+j];
sumj[j] += a[i*NUM+j];
}
}
if(sumx != sumy) return false;
for(i = 0; i < NUM; i++)
{
if(sumi[i] != sumj[i] || sumi[i] != sumx)
return false;
}
return true;
}int GetNumber(int n, int s)
{
int end = 0;
for(int i = n+s+1; ; i++)
{
end++;
if(i == last[n]) continue;
if(end > NUM*NUM)
{
return last[n];
}
if(i > NUM*NUM)
i -= NUM*NUM;
if(b[i])
{
b[i] = false;
last[n] = i;
return i;
}
}
}void lined(int n)
{
if(n == NUM*NUM) return;
for(int i = n; i < NUM*NUM; i++)
{
a[n] = GetNumber(n, i-n);
if(n == NUM*NUM-1)
{
count++;
if(IsMagic())
{
for(int k = 0; k < NUM; k++)
{
for(int j = 0; j < NUM; j++)
{
printf("%3d", a[k*NUM+j]);
}
printf("\n");
}
getchar();
result++;
}
}
lined(n+1);
b[last[n]] = true;
}
}void main()
{
for(int i = 0; i <= NUM*NUM; i++)
b[i] = true; lined(0);
}

解决方案 »

  1.   

    不会,upmatlab中有个命令,
    magic(n)
    它就会帮你生成了
      

  2.   

    不会,upmatlab中有个命令,
    magic(n)
    它就会帮你生成了
      

  3.   

    To maojincxj(毛巾) :
    您所说的magic(n)在哪里呀。
    我怎么找不到?
      

  4.   

    27!=10888869450418352160768000000how to calc in vc?freshman~#$())$#@!~#~@#@~~^^!@#!@~@~$$
      

  5.   

    谁能够写出幻方的算法思路。50分。
    代码:50分
    幻方问题见
    zswang(伴水清清)(专家门诊清洁工) 
    的贴子。
      

  6.   

    /*
    下面的程序是我消耗了N(n <= 9!)个脑细胞后新想出来的一个方法。
    贴出来,供大家参考。(只能用于三阶魔方阵。)
    只需要进行两重循环,即可得到所有可能的三阶魔方阵。
    1 2 3
    4 5 6
    7 8 9
    思路是:通过三阶魔方阵的特性。5必然居中。所有只要知道
    位置1, 2的两个数字,其它的数字可以通过计算求出来。
    用这个算法,只需要进行四十次计算,即可得到所有的三阶魔方阵。
    一共为8个
    */
    #include <stdio.h>int a[9], count, result;bool InA(int num)
    {
    if(num < 0 || num > 9) return true;
    for(int i = 0; i < 9; i++)
    if(num == a[i]) return true;
    return false;
    }bool make_magic()
    {
    int temp;
    count++;
    a[4] = 5;
    temp = 15-a[0]-a[1];
    if(InA(temp)) return false;
    else a[2] = temp;
    temp = 10 - a[0];
    if(InA(temp)) return false;
    else a[8] = temp;
    temp = 10 - a[2];
    if(InA(temp)) return false;
    else a[6] = temp;
    temp = 10 - a[1];
    if(InA(temp)) return false;
    else a[7] = temp;
    temp = 15-a[0]-a[6];
    if(InA(temp)) return false;
    else a[3] = temp;
    temp = 10 - a[3];
    if(InA(temp)) return false;
    else a[5] = temp; return true;
    }void print()
    {
    result++;
    for(int i = 0; i < 3; i++)
    {
    for(int j = 0; j < 3; j++)
    {
    printf("%3d", a[i*3+j]);
    }
    printf("\n");
    }
    getchar();
    }void init()
    {
    for(int i = 2; i < 9; i++)
    a[i] = 0;
    }void main()
    {
    for(int i = 1; i < 10; i++)
    {
    if(i == 5) continue;
    a[0] = i;
    for(int j = 1; j < 10; j++)
    {
    if(j == i || j == 5 || i+j < 6 || i+j > 14) continue;
    a[1] = j;
    if(make_magic())
    print();
    init();
    }
    }
    }
      

  7.   

    我想来想去还是要用遍历,想办法优化吧
    我估计可以在十秒内算出4x4的方阵[妈的!CSDN又生病了,昨晚恁是发表不了流言,真是弱]