惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
The Cloudflare Blog
博客园_首页
WordPress大学
WordPress大学
有赞技术团队
有赞技术团队
人人都是产品经理
人人都是产品经理
爱范儿
爱范儿
罗磊的独立博客
酷 壳 – CoolShell
酷 壳 – CoolShell
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Jina AI
Jina AI
美团技术团队
博客园 - 【当耐特】
博客园 - Franky
T
Tailwind CSS Blog
雷峰网
雷峰网
小众软件
小众软件
阮一峰的网络日志
阮一峰的网络日志
Apple Machine Learning Research
Apple Machine Learning Research
Last Week in AI
Last Week in AI
V
V2EX
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 三生石上(FineUI控件)

博客园 - erik168

C#事件的定义与触发[查找] join语法 DataAdpater的Fill研究 关于event的浏览器兼容问题-from佛 - erik168 - 博客园 表驱动法 javascript实现xslt转换xml - erik168 - 博客园 2个JS细节 DOM模型设置属性细节 - erik168 - 博客园 js的Hashtable类(转) - erik168 - 博客园 几个关于javascript的细节 .net的同步 .net线程基础知识 C#开发ActiveX控件 从数据库中查询所有表及所有字段的SQL语句(转) 保存javascript运行状态 解决IE访问域外信息警告对话框弹出 创建XmlHttpRequest - erik168 - 博客园 vi概况 [资料查找结果]一些SHELL要知道的东西 - erik168 - 博客园
幻方算法
erik168 · 2006-11-16 · via 博客园 - erik168

参考资料:http://mathworld.wolfram.com/MagicSquare.html

首先,奇数的幻方,第一行中间放1,然后依次2、3、4一直往右上填,越界则反向,如果该位置有了数字,则排在前一个数的下面。原则:非右上则下

其次,4的倍数的的幻方。设N%4等于0,则以每个4*4画对角,不在对角线上的数字与相对应数字对换。
比如8*8的,(0,1)与(7,6)对换,类推。原则:横竖下标对N比余,相等或相加等于3则忽略,不做对换

最后,最复杂的最后一种情况,单偶数的幻方。我找了资料,但是没有完全好用的,总有缺陷
概念:N=4m+2
方法1:
AC
DB
按上图将其分为4个部分,分别填入1-N*N/4组成的奇数幻方,N*N/4+1-N*N/2组成的奇数幻方,N*N/2+1-N*N/4*3组成的奇数幻方,N*N/4*3-N*N组成的奇数幻方
将AD中m列互换。不是镜面互换,而是平移。
将BC中m-1列互换,同上。
方法2:LUX法
L U X
41 14 14
23 23 32
先做一个N/2的奇数幻方,然后把这个幻方的每个数x替换成一个田字的四个数(x-1)*4+1——x*4
这四个数的排列顺序有3种,前m+1行的按L排列,后m-1行的按X排列,中间一行中间一列按L排列,其余的按U排列。
下面是我写的JAVA实现类,2种单偶数我都实现了(第一种方法的实现被我注释掉了),还有一个监测的方法,仅供参考。

public class HuanClass {
private int N;
private int SUM;
private int MAX;
private int[][] RE;
public HuanClass(int val) throws Exception{
N=val;
MAX=N*N;
if(MAX%2==1)SUM=(MAX+1)/2*N;
else SUM=(MAX+1)*N/2;
RE=new int[N][N];
if(N<3)
throw new Exception("shit");
else if(N%2==1)
RE=CountOdd(N);
else if(N%4==0)
CountFour();
else
CountEven();
}
private int[][] CountOdd(int n){
int[][] IRE=new int[n][n];
int i=0;
int j=n/2;
int tmp=1;
while(true){
if(j>=n)j=0;if(i<0)i=n-1;
if(IRE[i][j]==0){IRE[i--][j++]=tmp++;}
else{i+=2;j--;if(j<0)j=n-1;if(i>=n)i=i%n;
if(IRE[i][j]==0)IRE[i--][j++]=tmp++;
else break;
}
}
return IRE;
}
private void CountFour(){
int fillCount=1;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
RE[i][j]=fillCount;
fillCount++;
}
}
int tmp;
for(int i=0;i<N;i++){
for(int j=0;j<N/2;j++){
if(i%4!=j%4&&(j%4+i%4)!=3){
tmp=RE[i][j];
RE[i][j]=RE[N-i-1][N-j-1];
RE[N-i-1][N-j-1]=tmp;
}
}
}
}
/*
private void CountEven(){
int halfN=N/2;
int[][] tmpIArr=CountOdd(halfN);
for(int i=0;i<halfN;i++){
for(int j=0;j<halfN;j++){
RE[i][j]=tmpIArr[i][j];
RE[i+halfN][j]=tmpIArr[i][j]+halfN*halfN*3;
RE[i][j+halfN]=tmpIArr[i][j]+halfN*halfN*2;
RE[i+halfN][j+halfN]=tmpIArr[i][j]+halfN*halfN;
}
}
int m=(halfN-1)/2;
int tmp;
for(int j=0;j<m;j++){
for(int i=0;i<halfN;i++){
tmp=RE[i][j];
RE[i][j]=RE[i+halfN][j];
RE[i+halfN][j]=tmp;
if(j<m-1){
tmp=RE[i][j+halfN];
RE[i][j+halfN]=RE[i+halfN][j+halfN];
RE[i+halfN][j+halfN]=tmp;
}
}
}
}*/
private void CountEven(){
int halfN=N/2;
int m=(halfN-1)/2;
int[][] Seq=CountOdd(halfN);
char[][] SeqSign=new char[halfN][halfN];
for(int i=0;i<SeqSign.length;i++){
for(int j=0;j<SeqSign[i].length;j++){
SeqSign[i][j]='L';
}
}
int i=halfN-1;
for(int l=1;l<m;l++,i--){
for(int j=0;j<halfN;j++){
SeqSign[i][j]='X';
}
}
for(int j=0;j<halfN;j++){
if(j==halfN/2)
SeqSign[i][j]='L';
else
SeqSign[i][j]='U';
}
for(i=0;i<halfN;i++){
for(int j=0;j<halfN;j++){
int beginNum=(Seq[i][j]-1)*4;
switch (SeqSign[i][j]){
case 'L':
RE[i*2][j*2]=beginNum+4;
RE[i*2+1][j*2]=beginNum+2;
RE[i*2][j*2+1]=beginNum+1;
RE[i*2+1][j*2+1]=beginNum+3;
break;
case 'U':
RE[i*2][j*2]=beginNum+1;
RE[i*2+1][j*2]=beginNum+2;
RE[i*2][j*2+1]=beginNum+4;
RE[i*2+1][j*2+1]=beginNum+3;
break;
case 'X':
RE[i*2][j*2]=beginNum+1;
RE[i*2+1][j*2]=beginNum+3;
RE[i*2][j*2+1]=beginNum+4;
RE[i*2+1][j*2+1]=beginNum+2;
break;
}
}
}
}
public int[][] getHuan(){
return RE;
}
public boolean check(){
for(int i=0;i<N;i++){
int tmpSum1=0;
int tmpSum2=0;
for(int j=0;j<N;j++){
tmpSum1+=RE[i][j];
tmpSum2+=RE[j][i];
}
if(tmpSum1!=SUM||tmpSum2!=SUM)return false;
}
int sum1=0,sum2=0;
for(int i=0;i<N;i++){
sum1+=RE[i][i];
sum2+=RE[i][N-1-i];
}
if(sum1!=SUM||sum2!=SUM)return false;

return true;
}
}