#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语言编写的魔方阵 重要步骤的解释等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)