N阶幻方阵
来源:互联网 发布:手机淘宝掌柜热卖截图 编辑:程序博客网 时间:2024/04/28 21:26
幻方,亦称纵横图。台湾称为魔术方阵。将自然数1,2,3,……n*n排列成一个n*n方阵,使得每行、每列以及两对角线上的各个数之和都相等,等于n/2*(n*n+1),这样的方阵称为幻方。
例如:把1,2,3,4,5,6,7,8,9填入3*3的格子,使得:每行、每列、两条对角线的和是15。
816357492n是它的阶数,比如上面的幻方是3阶。n/2*(n*n+1)为幻方的变幻常数。数学上已经证明,对于n>2,n阶幻方都存在。
目前填写幻方的方法,是把幻方分成了三类,每类又有各种各样的填写方法。这里对于这三类幻方,仅举出一种方便手工填写的方法。
1、奇数阶幻方
n为奇数 (n=3,5,7,9,11……) (n=2*k+1,k=1,2,3,4,5……)
奇数阶幻方最经典的填法是罗伯特法(也有人称之为楼梯方)。填写方法是这样:
把1(或最小的数)放在第一行正中; 按以下规律排列剩下的n*n-1个数:
(1)、每一个数放在前一个数的右上一格;
(2)、如果这个数所要放的格已经超出了顶行那么就把它放在底行,仍然要放在右一列;
(3)、如果这个数所要放的格已经超出了最右列那么就把它放在最左列,仍然要放在上一行;
(4)、如果这个数所要放的格已经超出了顶行且超出了最右列,那么就把它放在前一个数的下一行同一列的格内;
(5)、如果这个数所要放的格已经有数填入,处理方法同(4)。
这种写法总是先向“右上”的方向,象是在爬楼梯。
快速算法:
#include<stdio.h>
int mod(int i,int p)
{
if(i>=0)return i%p==0?p:i%p;
else return p+i;
}
void main()
{
int i,j,p,n;
scanf("%d",&p);n=(p-1)/2;
for(i=1;i<=p;i++)
{
for(j=1;j<=p;j++)printf("%4d",p*(mod(i+j-n-1,p)-1)+mod(j+mod(i+j-n-1,p)-n-1,p));
printf("\n");
}
getch();
}
普通算法:
#include<stdio.h>
#include"malloc.h"
void main(void)
{
int i,j,n,N,a,b,temp1,temp2;
int *p;
puts("Please input the number!");
scanf("%d",&N);
p = (int *)malloc(sizeof(int)*N*N);
for(i = 0;i<N*N;i++)
p[i] = i+1;
for(n=1;n<=N;n++)
{
i=j=n;
a=(i-1)*N+j-1;
p[a]=N*N+1-p[a];
temp1=N-j+1;
a=(i-1)*N+temp1-1;
p[a]=N*N+1-p[a];
for(b=1;b<N/4;b++)
{
j=j+4;
temp2=j%N;
if(temp2==0)
temp2=8;
a=(i-1)*N+temp2-1;
p[a]=N*N+1-p[a];
temp2=N-temp2+1;
a=(i-1)*N+temp2-1;
p[a]=N*N+1-p[a];
}
}
for(i = 0;i<N*N;i++)
{
printf("%4d",p[i]);
if((i+1)%N == 0)
printf("\n");
}
}
2、双偶阶幻方
n为偶数,且能被4整除 (n=4,8,12,16,20……) (n=4k,k=1,2,3,4,5……)
先说明一个定义:
互补:如果两个数字的和,等于幻方最大数和最小数的和,即 n*n+1,称为互补。
先看看4阶幻方的填法:将数字从左到右、从上到下按顺序填写:
12345678910111213141516这个方阵的对角线,已经用蓝色标出。将对角线上的数字,换成与它互补的数字。
这里,n*n+1 = 4*4+1 = 17;
把1换成17-1 = 16;把6换成17-6 = 11;把11换成17-11 = 6……换完后就是一个四阶幻方。
16231351110897612414151对于n=4k阶幻方,我们先把数字按顺序填写。写好后,按4*4把它划分成k*k个方阵。因为n是4的倍数,一定能用4*4的小方阵分割。然后把每个小方阵的对角线,象制作4阶幻方的方法一样,对角线上的数字换成互补的数字,就构成幻方。 下面是8阶幻方的作法:
(1) 先把数字按顺序填。然后,按4*4把它分割成2*2个小方阵
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364(2) 每个小方阵对角线上的数字,换成和它互补的数。
64236160675795554121351501617474620214342244026273736303133323435292838392541232244451918484915145253111056858595462631算法实现:
#include<stdio.h>
#include"malloc.h"
void main(void)
{
int i,j,n,N,a;
int *p;
puts("Please input the number!");
scanf("%d",&N);
p = (int *)malloc(sizeof(int)*N*N);
for(i = 0;i<N*N;i++)
{
p[i] = 0;
}
i = 1;
j = N/2+1;
for(n=1;n<=N*N;n++)
{
if(i ==0 && j==N+1)
{
i = i+2;
j = j-1;
}
if(i == 0)
i = i+N;
if(j == N+1)
j = j-N;
a = (i-1)*N+j-1;
if(p[a] != 0)
{
i = i+2;
j = j-1;
}
a = (i-1)*N+j-1;
p[a] = n;
i = i-1;
j = j+1;
}
for(i = 0;i<N*N;i++)
{
printf("%4d",p[i]);
if((i+1)%N == 0)
printf("\n");
}
}
3、单偶阶幻方
n为偶数,且不能被4整除 (n=6,10,14,18,22……) (n=4k+2,k=1,2,3,4,5……)
这是三种里面最复杂的幻方。
以n=10为例。这时,k=2
(1) 把方阵分为A,B,C,D四个象限,这样每一个象限肯定是奇数阶。用楼梯法,依次在A象限,D象限,B象限,C象限按奇数阶幻方的填法填数。
A B C D 172418156774515865235714167355576466461320225456637072101219213606269715311182529616875525992997683904249263340988082899148303239417981889597293138454785879496783537444628869310077843643502734(2) 在A象限的中间行、中间格开始,按自左向右的方向,标出k格。A象限的其它行则标出最左边的k格。
>>>
172418156774515865235714167355576466461320225456637072101219213606269715311182529616875525992997683904249263340988082899148303239417981889597293138454785879496783537444628869310077843643502734(3) 将这些格,和C象限相对位置上的数,互换位置。
929918156774515865988071416735557646646889522545663707285871921360626971538693252961687552591724768390424926334023582899148303239417981132097293138454710129496783537444628111810077843643502734(4) 在B象限任一行的中间格,自右向左,标出k-1列。(注:6阶幻方由于k-1=0所以不用再作B、D象限的数据交换)
<<<
929918156774515865988071416735557646646889522545663707285871921360626971538693252961687552591724768390424926334023582899148303239417981132097293138454710129496783537444628111810077843643502734(5) 将B象限标出的这些数,和D象限相对位置上的数进行交换,即可完成。
929918156774265865988071416735532646646889522545638707285871921360624471538693252961685052591724768390424951334023582899148305739417981132097293163454710129496783537694628111810077843643752734
幻方阵c语言实现:
- N阶幻方阵
- 输出n*n阶方阵
- n阶方阵对角线之和
- 构造N*N阶的方阵
- 【Java实现】输出n阶螺旋方阵/旋转方阵
- N阶的螺旋方阵。。。。编程
- 求n阶方阵对角线之和
- N*N 的方阵
- N*N方阵
- N*N螺旋方阵
- 【每周一题】2、打印N*N阶的方阵
- 随机排列n*n方阵
- C语言 - 螺旋方阵:运动算法求任意n阶螺旋方阵
- 求教:用C++求n阶方阵对角线之和!
- 计算n阶行列式和方阵逆矩阵
- 求一个n阶方阵对角线元素之和
- 求一个n阶方阵对角线元素之和。
- Java作业-n阶方阵对角线元素之和
- Java中的instanceof关键字
- 编程语言的发展趋势及未来方向
- 最近公共祖先问题(LCA)
- hdu 1527 取石子游戏
- Java内存区域与内存溢出异常
- N阶幻方阵
- 阿里巴巴2014校园招聘研发笔试JAVA附加题
- 历史记录
- 约瑟夫环
- 条码扫描二维码扫描——ZXing android 简化源码分析
- vb报表的设计
- Android自定义照相机实现
- 项目管理中的快与慢
- Opencv2 学习笔记<一>:cv::Mat数据访问方式