求一个n阶魔方阵的算法!希望能用标准c++的风格来做!

求一个n阶魔方阵的算法!希望能用标准c++的风格来做!,第1张

#define sizem ((size / 2 - 1) / 2)

#define sizeh (size / 2)

#define sizesq (sizeh sizeh)

void main()

{

int size = 0; //幻方大小

int x = 0, y = 0; //下一个数字所放的位置

int i, j; //循环变量

int st_i, st_x = 0, st_y = 0;

int currnum; //构造双偶数阶幻方填数的变量

int temp;

//-----输入幻方大小-------------------------------

while ((size < 1) || (size > 31) || (size == 2))

{

printf("size of magic square:");

scanf("%d", &size);

}

//-----建立二维动态数组---------------------------

int a = new int [size];

for (i=0; i<size; i++)

{

a[i] = new int [size];

}

if (size % 2 == 1)

{

//-----构造奇数阶(2n+1)幻方(连续摆数法)---

x = (size + 1) / 2 - 1; //第一个数字在第一行

y = 0; //的正中间位置

//-----开始填数-------------------------------

for (i=1; i<=sizesize; i++)

{

a[y][x] = i;

//-----分析下一个数字的位置---------------

//-----当下一个数是size的倍数时,放在正下方

if (i % size == 0)

{

y++;

}

//-----当超出上面的边界时-----------------

else if (y == 0)

{

x++;

y = size - 1;

}

//-----当超出右面的边界时-----------------

else if (x == size - 1)

{

x = 0;

y--;

}

//-----正常情况下-------------------------

else

{

x++;

y--;

}

}

}

else if (size % 4 == 0)

{

//-----构造双偶数阶(4n)型幻方(对称法)-----

//-----第一步:分区并给分区做标记-------------

for (x=0; x<size/2; x++)

{

for (y=0; y<size/2; y++)

{

if ((x + y) % 2 == 0)

{

a[x][y] = -1;

a[x][size-y-1] = -1;

a[size-x-1][y] = -1;

a[size-x-1][size-y-1] = -1;

}

}

}

//-----第二步:填数-------------------------

for (x=0; x<size; x++)

{

for (y=0; y<size; y++)

{

currnum = x size + y;

if (a[x][y] == -1)

{

a[x][y] = size size - currnum;

}

else

{

a[x][y] = currnum + 1;

}

}

}

}

else

{

//-----构造单偶数阶(2(2m+1))幻方(斯特雷奇法)

//-----第一步:构造size/2阶幻方(连续摆数法)-

for (st_i=0; st_i<4; st_i++)

{

switch (st_i)

{

case 0:

st_x = 0;

st_y = 0;

break;

case 1:

st_x = sizeh;

st_y = sizeh;

break;

case 2:

st_x = sizeh;

st_y = 0;

break;

case 3:

st_x = 0;

st_y = sizeh;

break;

default:

break;

}

x = (sizeh + 1) / 2 - 1; //第一个数字在第一行

y = 0; //的正中间位置

//-----开始填数---------------------------

for (i=1; i<=sizesq; i++)

{

a[y+st_y][x+st_x] = i + sizesq st_i;

//-----分析下一个数字的位置---------------

//-----当下一个数是size的倍数时,放在正下方

if (i % (size / 2) == 0)

{

y++;

}

//-----当超出上面的边界时-----------------

else if (y == 0)

{

x++;

y = size / 2 - 1;

}

//-----当超出右面的边界时-----------------

else if (x == size / 2 - 1)

{

x = 0;

y--;

}

//-----正常情况下-------------------------

else

{

x++;

y--;

}

}//-----end of for(i)---------------------

}//-----end of for(st_i)

//-----第二步:交换A和D的第二行起m个数字------

for (j=1; j<sizem+1; j++)

{

temp = a[(sizeh+1)/2-1][j];

a[(sizeh+1)/2-1][j] = a[(sizeh+1)/2+sizeh-1][j];

a[(sizeh+1)/2+sizeh-1][j] = temp;

}

//-----第三步:交换A和D其它行的数字-----------

for (i=0; i<sizeh; i++)

{

if (i == (sizeh + 1) / 2 - 1)

{

continue;

}

for (j=0; j<sizem; j++)

{

temp = a[i][j];

a[i][j] = a[sizeh+i][j];

a[sizeh+i][j] = temp;

}

}

//-----第四步:交换C和B最后m-1行的数字

for (i=0; i<sizeh; i++)

{

for (j=size-1; j>size-sizem; j--)

{

temp = a[i][j];

a[i][j] = a[sizeh+i][j];

a[sizeh+i][j] = temp;

}

}

}//-----end of if(size % 2 == 0)

//-----输出幻方-----------------------------------

cout<<endl;

for (i=0; i<size; i++)

{

for (j=0; j<size; j++)

{

cout<<a[i][j]<<" ";

}

cout<<endl<<endl;

}

cout<<endl;

//-----清除数组-------------------------------

for (i=0; i<size; i++)

{

delete [] a[i];

}

delete [] a;

}

魔方还原软件是基于智能优化算法,致力于自动解决魔方问题,通过有效率的算法实现高效还原魔方目标。

全自动魔方还原软件的基本原理是,先将搅乱的魔方数据转换为状态矩阵,用优化算法计算从初始状态到目标状态的最短路径,再将每步的转换指令以及具体转换方式进行计算,根据推演结果控制机器执行魔方还原。

魔方还原软件使用的优化算法一般包括深度优先搜索算法,广度优先搜索算法,A算法,IDA算法,迭代加深搜索算法等。深度优先搜索算法由于开销大,容易爆发出空间,并没有在魔方还原中得到应用;广度优先搜索算法虽然耗费的开支低,但是搜索效率不高,也没有得到应用;A算法可以快速的找出最优路径,但是也有可能无法找到最优路径;IDA算法在A算法的基础上加以改进,使得在搜索过程中更加节省时间,可以更快的找到最优路径;迭代加深搜索算法可以保证找出最优路径,但是由于耗费的开销,一般不会用于魔方还原中。

目前,魔方还原软件一般采用IDA优化算法,比对状态矩阵,计算出最优化路径,快速还原魔方,实现全自动还原魔方的目标。

其实这个只能实现奇数阶的魔方阵输出

奇数阶的魔方阵有如下规律,根据这个规律编程就是LZ所写的代码了,LZ根据规律来看代码就应该可以清楚了

算法:

魔方阵的排列规律(奇数阵):

⑴将1放在第一行中间一列。

⑵从2开始直到n×n止各数依次按下列规则存放:每一个数存放的行比前一个数的行数减1,列数加1。

⑶如果上一个数的行数为1,则下一个数的行数为n,列数加1。如果上一个数的列数的n时,下一个数的列数为1,行数减1。

⑷如果按上面的规则确定的位置上已有数,或上一个数是第一行第n列时,则把下一个数放在上一个数的下面。

早期完全是人脑思考,现在是有电脑解法了。

人脑解法就是先划分局部目标,利用抵消和循环动作不破坏已经拼好的部分,然后逐步完成全部。在尝试中积累到更多经验的时候,就可以逐渐减少局部目标的数量,同时难度也提高了,不过总步数却减少了。减少步数就是最终方向了,它说明了思考更具全局性。

我无法预测人脑最后能不能进化成完全立足全局进行思考,但我知道那很遥远,因为人们太不注重优生了,总是随便凑一对解决性饥渴就行了,然后就一辈子捆上了。

我不知道别人是在什么样的状态下解出魔方,我是在快乐的忘我状态下解魔方的,也许是“入定”也许不是,培养起持续思考的能力的人应该各有各的状态吧。我是沿袭了解残棋时养成的习惯,思考时有脑内按摩的快感。不过现在快感的阈值总在提高,残棋早已没有快感了。

我尝试了用自己所能想出的所有顺序去拼魔方,也就是进行各种不同的局部目标划分,因此可能积累的经验要比多数人稍多一点,不过这一定只是解法中微小到无限的部分。我不确定解法无限,但确定再高的智商也一生研究不完。因此,棋和魔方我都不会花一生时间沉醉其中,适当用来娱乐就行了。

提一下中心块吧,6块相对位置是不变的,但有原地转的自由。因此6色魔方和拼图魔方是有些不同,6面带图案的是真复原,6色的通常由人脑来处理就不是真复原。3阶魔方解法也就这两类,各种还原顺序都不能算类,包括一些蒙眼小丑的表演都不能算类。

不多说了,最后纠正一下你的认识。一般人就可以解魔方,只要培养起思考方法。

哎,为了你这个小东西,大半夜的,我在这机子上装了个VC。

以下是用C文件写的,调试通过,产生哪个啥破矩阵。

先给你几个建议。

1写程序,只是一个流程翻译的过程。遵循“从上至下,由简至精”的翻译原则。

2写程序前,你得先有个算法或者是流程。别瞎写,这不是流水账。

3写程序中,你总得来点注释吧。你这么个写法叫哥咋看。

4写程序后,你也要有点总结吧。不总结永远不会有大的提高。

5你说你不会太难的,我写你看的懂得。但是看懂后,水平提高也不会那么多。

蛋疼的分割线

#include<stdioh>

main()

{

int a[10][10]={0},x,num,zuobiao_r,zuobiao_l,a_bianjie,i; //啥变量都在这定义

scanf("%d",&x); //输入个阶层数x

zuobiao_r=x/2; //E文不好 用拼音代替了 这个是坐标值 确定自然数1的坐标

zuobiao_l=0;

a_bianjie=x-1; //矩阵的边界

a[zuobiao_r][zuobiao_l]=1; //先把这个1给写入了

for(i=2;i<=xx;i++) //从2开始到xx打止 循环x-1次 i值是要填写的数值 循环累加

{

if(zuobiao_r==a_bianjie) //计算下一个的横坐标

zuobiao_r=0;

else

zuobiao_r++;

if(zuobiao_l==0) //计算下一个纵坐标

zuobiao_l=a_bianjie;

else

zuobiao_l--;

if(a[zuobiao_r][zuobiao_l]!=0) //如果下一个坐标是有数据的

{

if(zuobiao_r==0) //退回上一个横坐标

zuobiao_r=a_bianjie;

else

zuobiao_r--;

if(zuobiao_l==a_bianjie) //退回上一个纵坐标

zuobiao_l=0;

else

zuobiao_l++;

zuobiao_l++; //纵坐标往下挪一个

}

a[zuobiao_r][zuobiao_l]=i; //在坐标上写入i值

}

for(zuobiao_r=0;zuobiao_r<=a_bianjie;zuobiao_r++) //输出整个矩阵

{

for(zuobiao_l=0;zuobiao_l<=a_bianjie;zuobiao_l++)

{

printf("%d\t",a[zuobiao_l][zuobiao_r]);

}

printf("\n"); //别忘记这个换行了

}

}

/

所谓魔方阵是指这样的的方阵:

它的每一行、每一列和对角线之和均相等。

输入n,要求打印由自然数1到n2的自然数构成的魔方阵(n为奇数)。

例如,当n=3时,魔方阵为:

 8 1 6

 3 5 7

 4 9 2

魔方阵中各数排列规律为:

① 将“1”放在第一行的中间一列;

② 从“2”开始直到n×n为止的各数依次按下列规则存放:每一个数存放的行比前一个数的行数减1,列数同样加1;

③ 如果上一数的行数为1,则下一个数的行数为n(最下一行),如在3×3 方阵中,1在第1行,则2应放在第3行第3列。

④ 当上一个数的列数为n时,下一个数的列数应为1,行数减1。如2在第3行第3列,3应在第2行第1列。

⑤如果按上面规则确定的位置上已有数,或上一个数是第1行第n列时,则把下一个数放在上一个数的下面。

如按上面的规定,4应放在第1行第2列,但该位置已被1占据,所以4就放在3的下面。由于6是第1行第3列(即最后一列),故7放在6下面。

/

#include"stdioh"

void main()

{

int i,n=5;

printf("---------------打印魔方阵-------------\n\n");

int a[5][5];

for( i=0;i<n;i++)

for(int j=0;j<n;j++)

a[i][j]=0;//初始化

i=0;

int j=n/2;

int t=1;

int si=0;

int sj=0;//记录上一个数的位置

while(t<=nn)

{

//printf("\n%4d\n\n",t);

if(a[i][j]==0)

a[i][j]=t;

else

{

if(si==0 && sj==n-1)

{

a[si+1][sj]=t;

i=si+1;

j=sj;

}

if(si!=n-1)

{

a[si+1][sj]=t;

i=si+1;

j=sj;

}

if(si==n-1)

{

a[0][sj]=t;

i=0;

j=sj;

}

}

si=i;

sj=j;

/计算下一个元素的位置/

if(i==0)

i=n-1;

else

i=i-1;

if(j==n-1)

j=0;

else

j=j+1;

t=t+1;

}

for(i=0;i<n;i++)

{

for(int j=0;j<n;j++)

printf("%4d",a[i][j]);

printf("\n\n");

}

}

以上就是关于求一个n阶魔方阵的算法!希望能用标准c++的风格来做!全部的内容,包括:求一个n阶魔方阵的算法!希望能用标准c++的风格来做!、魔方还原软件原理、C语言编写的魔方阵 重要步骤的解释等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9711696.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存