第四次关于魔方阵的问题

syl08341 2003-06-15 06:38:51
http://expert.csdn.net/Expert/topic/1789/1789521.xml?temp=2.091616E-02
http://expert.csdn.net/Expert/topic/1767/1767284.xml?temp=.707348
http://expert.csdn.net/Expert/topic/1732/1732898.xml?temp=.3096125

什么是魔方阵?
魔方阵是由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阶魔方阵,机器就无法算出结果了。


有一个思路,可是无法编写出来代码。
每次两个数字交换位置,通过交换位置来排列出魔方阵的所有可能。
比如第一次是头两个数字交换位置,
第二次是第三个和第一个交换位置,
第三次是第三个和第二个交换位置…
谁能够用把这个思路的代码写出来?
...全文
144 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
syl08341 2003-06-15
  • 打赏
  • 举报
回复
不错不错。
你是学计算机还是数学的?
别告诉我是学其它的。
那样太打击我信心了。
这个程序我想了N久都没有想出来。
谢谢你帮我解决。
如果需要分的话,尽管开口。
chuyangguangshin 2003-06-15
  • 打赏
  • 举报
回复
你用这个算法看看计算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]);
}
}
}

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧