无聊之作:幻方问题 ( 全 )

闲来无聊。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

 

>>>>>>>>>>>>>>>>>>>>>>>>>>>>幻方大全>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

 

1、奇幻方  N=2*M+1(M=1,2,3,……)的布阵规律  

a、把1放在N*N方阵中的第一行中间一列,即放在位置为(1,(N+1)/2);   
b、后一个数存放的行数比前一个数存放的行数减1,若这个行数为0,则取行数为N;  
c、后一个数存放的列数比前一个数存放的列数加1,若这个列数为N+1,则取列数为1;  

d、如果前一个数是N的倍数,则后一个数存放的列数不变,而行数加1。

#include<stdio.h>
#include<stdlib.h>

int main()
{
 int M, N, i, j;
   
 printf("Please input M = ");
 scanf( "%d", &M );
 N = M * 2 - 1;
 
 if ( N % 2 == 0 )
 {
  N++;             //!> 保证是奇数
 }

 int ** numArray= ( int ** )malloc( N * sizeof( int * ));   //!> 注意malloc是默认是void*返回值,所以一般需要强转
 for ( i = 0; i < N; i ++ )
 {
  numArray[i] = ( int * )malloc(N * sizeof( int ));      //!> 大小有用户输入
 }

 for ( i = 0; i< N; i++ )
 {
  for ( j = 0; j <N; j++ )
  {
   numArray[i][j]= 0;
  }
 }
   //>>>>>>>>>>>>>>>>
 
 numArray[0][N/2] =1;           //!> a

 int  nextNum =2;
 int  numHaveLeft = N * N -1;
 int  hang = 0;
 int  lie  = N /2;

 while(numHaveLeft )
 {

  if ( ( nextNum - 1 )% N == 0 )
  {
   hang++;
  }
  else
  {
   hang--;
   if ( hang ==-1 )
   {
    hang= N - 1;
   }
   
   lie++;
   if ( lie == N)
   {
    lie= 0;
   }
  }

  numArray[hang][lie] =nextNum++;
  
  numHaveLeft--;
 }
 
 for ( i = 0; i < N; i++ )
 {
  for ( j = 0; j <N; j++ )
  {
   printf("%-3d ", numArray[i][j]);
  }
  printf("\n");
 }

 return 0;
}

 

 

2、偶幻方N=4*(M=1,2,3,……)的布阵规律先将1至N*N由小到大的顺序,从第一行开是依序填入N*N的方阵中,然后将N*N的方阵以4行4列划分为若干个4*4的小方阵,再将所有4*4小方阵的两个对角线上的数字划掉,之后将所有被划掉的数字重新由大到小的进行排列,然后再将这些数字按排列顺序由N*N方阵的第一行开始,放入被划掉的格子中去。则此时的偶幻方也就布好阵了


#include<stdio.h>
#include<stdlib.h>

#define                       //!> 注意N必是4的倍数

void sort( int arr[], int count)
{
 int i, j, temp;
 
 for ( i = 1; i < count; i++)
 {
  for ( j = 0; j <count - i; j++ )
  {
   if ( arr[j]< arr[j+1] )
   {
    temp= arr[j];
    arr[j]= arr[j+1];
    arr[j+1]= temp;
   }
  }
 }
}


int main()
{
 int numArray[N][N];
    int t, i, j,x, y;
    int numInto= 0; 
    inttempArray[10];
 
 for ( i = 0; i < N; i++ )
 {
  for ( j = 0; j <N; j++ )
  {
   numArray[i][j]= ++numInto;
  }
 }

 int startHang =0;              //!> 其实只要知道其实的航和列就可以了,因为4是固定不改变的!
 int startLie  = 0;
       
 for ( ; startHang < N; startHang+= 4 )  //!>注意怎么分成小块的,其实也就是整体上的for。。。
 {
  t = 0;
  
  for ( ; startLie< N; startLie += 4 )
  {
   t = 0;
   for ( x = 0,y = 0; x < 4 && y< 4; x++, y++)                   //!> 将做对角线放进temp数组
                   //!> 为了方便计算,置0 
    tempArray[t++]= numArray[startHang+x][startLie+y];
    numArray[startHang+x][startLie+y]= 0;
   }
   for ( x = 0,y = 3; x < 4 && y>= 0; x++, y--)                  //!> 将有对角线放进temp数组
   {
    tempArray[t++] = numArray[startHang+x][startLie+y];
    numArray[startHang+x][startLie+y] = 0;
   }
   
   sort(tempArray, t);                                            //!> 排序
   
   t = 0;
   for ( x = 0;x < 4; x++)           //!> 写回 
   {
    for( y = 0; y < 4; y++ )
    {
     if( numArray[startHang+x][startLie+y] == 0 )
     {
      numArray[startHang+x][startLie+y]= tempArray[t++];
     }
    }
   }

  }
 }

 for ( i = 0; i< N; i++ )
 {
  for ( j = 0; j <N; j++ )
  {
   printf("%-3d  ", numArray[i][j] );
  }
  printf("\n");
 }

 return 0;
}

 

3、偶幻方N=2*(2*M+1)(M=1,2,3,……)的布阵规律先将N*N的方阵划分为2*2的四个小方阵,设为A,B,C,D,则这四部分都正好是奇行奇列的方阵,设每个小方阵为U*U,其中U=N/2。然后将1至U*U按奇幻方的的方式填入小方 阵A中,同理填入U*U+1至U*U*2到B中,填入U*U*2+1至U*U*3到C中,填入U*U*3+1至U*U*4到D中。然后按下列方法交换:  
a、将A和D的第一列对应位置的元素(出各自的中间一行外)进行交换;  

b、将A和D的中间一列的中间一行的元素进行交换;  
c、如果(U+1)/2>2,则将A和D中左边的第二列开始到第(U-1)/2列为止,对应行的数字全部进行交换,同时将B   和C右边第一列起连续(U-1)/2-1列对英航的数字也全部进行交换。
  


#include<stdio.h>
#include<stdlib.h>

#define M 1
#define N  2 * ( 2 * M + 1 )

int main()
{
 int numArray[N][N];
 int startHang = 0;
 int startLie  = 0;
 int numStart  = 1;
 int i, j, x, y, temp;


 for ( x = 0; x< 2; x++ )
 {
  for ( y = 0; y <2; y++ )
  {
   for ( i =startHang; i < startHang + N / 2; i++ )
   {
    for( j = startLie; j < startLie + N / 2; j++ )
    {
     numArray[i][j]= numStart++;
    }
   }
   startLie += N/ 2;
  }
  startLie  = 0;
  startHang += N / 2;
  
 for ( i = 0; i < N / 2; i++)              //!> a
{
  if ( i != N / 4 )
  {
   temp =numArray[i][0];
   numArray[i][0]= numArray[N/2+i][N/2];
   numArray[N/2+i][N/2]= temp;
   }
 }

 temp =numArray[N/4][N/4];                 //!> b
 numArray[N/4][N/4] =numArray[N/2+N/4][N/4+N/2];
 numArray[N/2+N/4][N/2+N/4] =temp;


 for ( i = 0; i< N; i++ )
 {
  for( j = 0; j <N; j++ )
  {
   printf("%d ", numArray[i][j]);
  }
  printf("\n");
 }
 printf("\n\n");

 if ( ( N / 2 + 1) / 2 > 2 )
 {
  for ( j = 1; j<= ( N / 2 - 1 ) / 2; j++ )
  {
   for ( i = 0;i < N / 2; i++ )
   {
    temp= numArray[i][j];
    numArray[i][j]= numArray[N/2+i][N/2+j];
   }
  }

  for ( i = 0, x = N /2; i < N / 2 && x< N; i++, x++ )
  {
   for ( j = N /2, y = 0 ; j < N &&y < N / 2; y++, j++ )
   {
    temp= numArray[i][j];
    numArray[i][j]= numArray[x][y];
    numArray[x][y]= temp;
   }
  }
 }

 
 for ( i = 0; i < N; i++ )
 {
  for( j = 0; j <N; j++ )
  {
   printf("%d ", numArray[i][j]);
  }
  printf("\n");
 }
 

 return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值