你用这个算法看看计算3阶的魔方数列要多少时间,假设是time,那么计算5阶魔方就要25*24*23*....*9*time时间。这是你采取这种方法---全排列---的必然结果,所以这个算法理论上可以做无穷大阶的魔方,但是由于速度的原因它只能做3阶的来说明以下自身的正确性而已。
/****************************************************************
要对一个数组进行全排列可以这样进行:
把一个长度为n的数组的全部元素依次与第一位的元素交换,每一次交换后对
后面的n-1长度的数组进行全排列,然后再把那个交换的数放会原位。
----------显然这是一个递归算法。-----------------
递归结束的条件就是n==2,因为对两个数可以直接两次交换完成全排列。
****************************************************************/
#include <iostream.h>
#include <conio.h>
#include <math.h>
#define LEN 25
#define swap(a,b) do{if(a!=b){a^=b;b^=a;a^=b;}}while(0); //交换两个数据
/*****************************************************************
申请动态数组,ARRAY(type,name,ln,col)申请一个ln行col列的type型二维
数组,名为name;DELETE(name,ln,col)删除一个ln行col列的动态数组。
*****************************************************************/
#define ARRAY(type,name,ln,col) \
type **name=new type* [ln];\
for(int newloop=0;newloop<col;newloop++)\
name[newloop]=new type[col];
#define DELETE(name,ln,col) \
do{\
for(int dloop=0;dloop<ln;dloop++)\
delete [col]magic[dloop];\
delete [ln]magic;\
}while(0);
/***************************************************************
AllPermulation:(全排列函数) template <class T>
template:
T 目标数组的类型
Parameters:
operation 一个void(T array[],int n)类型的函数指针,全排
列函数每找到一种排列就把这个数组以及元素个数
传给operation调用.
array[LEN] 一个要进行全排列的长度为LEN的T类型的数组。
n 尽管这个数组的长度为LEN,但是只对前n个元素进
行全排列
Remark:
这个全排列函数的调用前后,所有元素的位置保持不变。
****************************************************************/
template <class T>
void AllPermutation(void (*operation)(T array[LEN],int n),T array[LEN],int n);
void judge(int array[LEN],int n);
int **magic;
int main()
{
int array[LEN],n;
cout<<"Please input n:"<<endl;
cin>>n;
if(n*n>25)
{
cout<<"n is too larger"<<endl;
return 0;
}
for(int i=0;i<n*n;i++)
array[i]=i+1;
ARRAY(int,temp,n,n);
magic=temp;
AllPermutation<int>(judge,array,n*n);
cout<<"Press any key to exit..."<<endl;
getch();
DELETE(temp,n,n);
return 0;
}
void judge(int array[LEN],int n) //判断是否满足魔方条件
{
int m=(int)(sqrt(n)+0.1),count=0,sum,sumln,sumcol,corner1,corner2;
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
magic[i][j]=array[count++];
sum=corner1=corner2=0;
for(i=0;i<m;i++)
{
sum+=magic[0][i];
corner1+=magic[i][i];
corner2+=magic[i][m-i-1];
}
if(corner1!=sum||corner2!=sum)
return;
for(i=0;i<m;i++)
{
sumln=sumcol=0;
for(int j=0;j<m;j++)
{
sumln+=magic[i][j];
sumcol+=magic[j][i];
}
if(sumln!=sum||sumcol!=sum)
return;
}
for(i=0;i<m;i++)
{
for(int j=0;j<m;j++)
cout<<magic[i][j]<<" ";
cout<<endl;
}
cout<<endl;
}
template <class T>
void AllPermutation(void (*operation)(T array[LEN],int n),T array[LEN],int n)
{
//keep记录数组的长度,因为n在递归过程中起了变化。 arraykeep同样的道理
static int keep=n;
static T *arraykeep=array;
if(n==2) //进行两个数的全排列
{
swap(array[0],array[1]);
(*operation)(arraykeep,keep); //自定义的函数
swap(array[0],array[1]);
(*operation)(arraykeep,keep);
}
else
{
for(int i=0;i<n;i++)
{
//把数组中的每一个元素依次放在首位
swap(array[0],array[i]);
//对后面的n-1长度的数组进行全排列
AllPermutation(operation,array+1,n-1);
//把交换的数再交换回来
swap(array[0],array[i]);
}
}
}