求解散 怎么用java实现一个5X5的螺旋循环队列的实现

题目:运用java二维数组打印“魔方阵”。所谓魔方阵是指这样的矩阵,它的每一行、每一列和对角线之和均相等,要求打印1~25之间由自然数构成的魔方阵。
这个已经不算什么新问题,当然也不算什么难题,但对于初学者来说,还是有一定难度的。我相信“万能的”度娘已经可以给出让大家满意的答案,但我以一个入门学生的角度来看这一题,当然第一个浮现的方法就是“枚举法”!(最粗暴的办法,毫无技巧可言!)
我个人是这样想的,既然是1~25个数,那么运用高中所学的排列组合知识可以看出,“魔方阵”只是一种特殊的排列情况,那么将所有的排列可能列出,再通过条件筛选出符合“魔方阵”的排列即可(这是我未曾深入了解“魔方阵”的第一个想法,其实这个办法你仔细分析便可得知,时间复杂度非常的大,5X5的组合情况有25!种,再进行条件筛选,工程浩大)。
简单分析下:1~25个数,每行每列对角线和都相等,对角线和列先不考虑,那么每行的和都相等,每一行的和相加就是1+2+3+4+…+25 = 13*25 ,每一行的和就是13*5,同理,每一列的和也为25,对角线也是,那么找到一个排列可能,只需满足此条件即可。
public class MFZ {
int[] used = new int[25];
= new int[25];
= new int[25];
public MFZ(){
for(int i = 0;i& 25;i++) mat[i] = i+1;
void magic_cube(int index){
int[][] magic = new int[5][5];
if(index &= 25) {
int yes = 1;
for(int i = 0;i & 5;i++)
for(int j = 0;j & 5;j++)
magic[i][j] = num[i*5+j];
for(int i = 0; i & 5;i++){
for(int j = 0;j &5 ;j++){
sum += magic[i][j];
if(sum != 65) {yes = -1;return;}
if(yes==1){
for(int j = 0; j & 5;j++){
for(int i = 0;i &5 ;i++){
sum += magic[i][j];
if(sum != 65) {yes = -1;return;}
if(yes==1){
if(magic[0][0]+magic[1][1]+magic[2][2]+magic[3][3]+magic[4][4]!=65){ yes = -1;return;}
if(magic[4][0]+magic[3][1]+magic[2][2]+magic[1][3]+magic[0][4]!=65){ yes = -1;return;}
if(yes==1) {
for(int i = 0;i & 5;i++){
for(int j = 0;j & 5;j++)
System.out.print(magic[i][j]+"
System.out.print("\n");
System.out.print("-----------------分割线----------------\n");
for(int i = 0;i & 25;++i){
if(used[i]==0){
used[i]=1;
num[index]=mat[i];
magic_cube(index+1);
used[i]=0;
public static void main(String[] args) {
MFZ a = new MFZ();
a.magic_cube(0);
其实这种方法理论上是可行的,但是实际上未必可行。因为时间复杂度太大,以上代码中注释行有一个被注释掉的类变量,你可以把这几行代码加进去运行,可以看到MFZ方法一共跑了多少次,当所求矩阵为5X5,eclipse在我的电脑上跑的时候瞬间就跑了300w次,还没跑完!然后我又等了几分钟,还是没跑出来。
跑不出来不代表这个方法不行!我们可以将代码中的25改成9,5改成3,对角线修改一下,那么MFZ方法就变成求“3x3魔方阵”,在我的电脑上瞬间就跑出来了。
其实这并不算一个失败的结果,没错,求“5x5魔方阵”确实失败,但我了解到了即使一个正确的思路,也未必可以得到想要的结果。
其实作为一个初学者,可以看到写出一个让计算机的运算速度捉襟见肘也是一件蛮有趣的事。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:266次
排名:千里之外(1.1)编程基础之基本知识(34)
http://blog.csdn.net/yhmhappy2006/article/details/2934435
螺旋队列的样子如下图:
两大规律:
1、螺旋规律
2、奇数(圈数,或X轴正坐标)平方规律(紫线)
问题描述:
设1的坐标是(0,0),x方向向右为正,y方向向下为正,例如,7的坐标为(-1,-1),2的坐标为(1,0)。编程实现输入任意一点坐标(x,y),输出所对应的数字!
问题解决:
从紫线突破。
从图中不难发现,每圈最大值max=(2*c+1)(2*c+1),c为由内往外的圈数,c&=0。如图每圈最大值分别是1、9、25、49、81........,算出每圈的max后,就分4条边分别计算每圈的其他值。通过坐标落在该圈4条边的哪条边上,按照不同的公式计算出具体坐标点的值。
以第3圈(max=49)为例,4条边划分如下图(以颜色区分):
这里先给出4条边上各坐标上的值与max的对应关系为:
上边:Utop = max+(x+y);
左边: Uleft= max+(3*x-y);
下边:Ubottom = max + (-x - 5*y);
右边:Uright = max+(-7*x+y);
那么这些关系是怎么得出来的呢?再看图中画上圈的数字(将其值表示为topBase,xxBase),我们称其为每条边的基准值:
在上边,y坐标不变,x坐标变化步长为1。令x=0,此时,topBase=max+y作为该边的基准值,其他值随x的变化而变化,得在该区域u=max+y+x;
同理,在左边,x坐标不变,y坐标变化步长为1。令y=0,此时,u=max+3*x作为该边的基准值,其他值随y的变化而变化,得在该区域u=vc+3*x-y;
同理得其他俩区域的表达式。不再赘述。
&观察这些基准值与max值之间关系,不难发现,这些基准值与max之间的差分别是1C(上边),3C(左边),5C(下边),7C(右边)(C表示当前圈数),在上边和下边,y坐标表示(或等于)圈数(即C=y),而在左边和右边,x坐标表示(或等于)圈数(即C=x)。因此前面提到的差值又可用坐标表示成1y,3x,5y,7x。因此就产生了各边基准值的计算公式:
topBase=max+y
leftBase=max+3x
bottomBase=max-5y
rightBase=max-7x
(注意坐标的符号,负数加,正数减,因为基准值肯定都比max要小)
下面得出每条边的值,首先考虑上边和下边,这2条边,在基准值的基础上,由x坐标控制增减,因此:
topValue=topBase+x=max+y+x(上边,随x赠而赠,因此是加x)
bottomValue=bottomBase-x=max-5y-x(下边,随x赠而减,因此是减x)
同理,左边和右边,则在基准值的基础上,由y坐标控制增减,因此:
leftValue=leftBase-y=max+3x-y(左边,随y赠而减,因此是减y)
rightValue=rightBase+y=max-7x+y(右边,随y赠而赠,因此是加y)
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:198347次
积分:4606
积分:4606
排名:第5085名
原创:178篇
转载:587篇数据结构与算法(7)
看清以上数字的排列规律,设1点的坐标是(0,0),x方向向右为正,y方向向下为正。例如,7的坐标为(-1,-1),2的坐标为(1,0),3的坐标为(1,1)。编程实现输入任意一点坐标(x,y),输出所对应的数字。
规律能看出来,问题就在于如何利用它。很明显这个队列是顺时针螺旋向外扩展的,我们可以把它看成一层一层往外延 伸。第 0 层规定为中间的那个 1,第 1 层为 2 到 9,第 2 层为 10 到 25,注意到 1、9、25、……不就是平方数吗?而且是连续奇数(1、3、5、……)的平方数。这些数还跟层数相关,推算一下就可以知道第 t 层之内一共有 (2t-1)^2 个数,因而第 t 层会从 [(2t-1)^2] + 1 开始继续往外螺旋。给定坐标 (x,y),如何知道该点处于第几层?层数 t = max(|x|,|y|)。
知道了层数,接下来就好办多了,这时我们就知道所求的那点一定在第 t 层这个圈上,顺着往下数就是了。要注意的就是螺旋队列数值增长方向和坐标轴正方向并不一定相同。我们可以分成四种情况——上、下、左、右——或者——东、南、西、北,分别处于四条边上来分析。
东|右:x == t,队列增长方向和 y 轴一致,正东方向(y = 0)数值为 (2t-1)^2 + t,所以 v = (2t-1)^2 + t + y
南|下:y == t,队列增长方向和 x 轴相反,正南方向(x = 0)数值为 (2t-1)^2 + 3t,所以 v = (2t-1)^2 + 3t - x
西|左:x == -t,队列增长方向和 y 轴相反,正西方向(y = 0)数值为 (2t-1)^2 + 5t,所以 v = (2t-1)^2 + 5t - y
北|上:y == -t,队列增长方向和 x 轴一致,正北方向(x = 0)数值为 (2t-1)^2 + 7t,所以 v = (2t-1)^2 + 7t + x
其实还有一点很重要,不然会有问题。其它三条边都还好,但是在东边(右边)那条线上,队列增加不完全符合公式!注意 到东北角(右上角)是本层的最后一个数,再往下却是本层的第一个数,那当然不满足东线公式啊。所以我们把东线的判断放在最后(其实只需要放在北线之后就可 以),这样一来,东北角那点始终会被认为是北线上的点。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:639485次
积分:5120
积分:5120
排名:第4296名
原创:120篇
转载:39篇
评论:94条
(1)(2)(1)(1)(1)(1)(6)(1)(1)(2)(3)(2)(1)(7)(2)(2)(4)(2)(4)(1)(1)(1)(1)(1)(2)(4)(11)(8)(9)(29)(19)(6)(1)(9)(1)(1)(1)(5)(4)}

我要回帖

更多关于 c语言队列实现 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信