魔方阵:3阶、4阶、8阶算法与实现

魔方阵:一个N阶魔方阵即N行N列的数组,其每一行的和==每一列的和==对角线的和。
例如一个3阶魔方阵:
8  1  6
3  5  7
4  9  2

一:3阶魔方阵

这里我们用两种方法实现:

方法一:遍历三阶数组的所有条件,将符合条件的(行的和==列的和==对角线和)挑出来。这种方法可以打印出多种情况。

方法二:
1.将1放在第一行的中间
2.后面的数字放在当前数字的的上一行后一列 
3.如果当前位置有数据,就放在前一个数字的下一行同列

方法一代码:
bool TiaoJian_1(int  arr[3][3])//魔方阵的条件:9个数字互不相等
{
            if(arr[0][0] != arr[1][0] && arr[0][0] != arr[1][2] && arr[0][1]!= arr[1][1] && 
               arr[0][0] != arr[0][1] && arr[0][1] != arr[0][2] && arr[0][2] != arr[1][0]&&  
               arr[1][0] != arr[1][1] && arr[1][1] != arr[1][2] && arr[1][2] != arr[2][0]&&
               arr[2][0] != arr[2][1] && arr[2][1] != arr[2][2] && arr[1][0]!= arr[2][0])
            {
                return true;
            }
            else
            {
                return false;
            }
}

bool Tiaojian_2(int h[3],int l[3],int dj[2])
{
    if(h[0]==h[1] && h[1]==h[2] && h[2]==l[0] && 
       l[0]==l[1] && l[1]==l[2] && l[2]==dj[0] &&dj[0]==dj[1])
    {
        return true;
    }
    else
    {
        return false;
    }
}
int MagicCube_3()
{
    int arr[3][3];
    int h[3];
    int l[3];
    int dj[2];
    int n = 10;

    
        for(int i1 = 1;i1<n;i1++)//给3*3个元素分别赋值1~10,共9^9种情况;一个for循环一个元素,共9个
        {
            arr[0][0] = i1;
            for(int i2 = 1;i2<n;i2++)
            {
                arr[0][1] = i2;
                for(int i3 = 1;i3<n;i3++)
                {
                    arr[0][2] = i3;
                    for(int j1 = 1;j1<n;j1++)
                    {
                        arr[1][0] = j1;
                        for(int j2 = 1;j2<n;j2++)
                        {
                            arr[1][1] = j2;
                            for(int j3 = 1;j3<n;j3++)
                            {
                                arr[1][2] = j3;
                                for(int k1 = 1;k1<n;k1++)
                                {
                                    arr[2][0] = k1;
                                    for(int k2 = 1;k2<n;k2++)
                                    {
                                        arr[2][1] = k2;
                                        for(int k3 = 1;k3<n;k3++)
                                        {
                                            arr[2][2] = k3;

                                            if(TiaoJian_1( arr ))
                                           {

                                               for(int i = 0;i <= 3;i++)//h[0]  h[1]  h[2]
                                               {
                                                     h[i] = arr[i][0]+arr[i][1]+arr[i][2];
                                                     l[i] = arr[0][i]+arr[1][i]+arr[2][i];
                                               }
                                                                        
                                                dj[0] = arr[0][0]+arr[1][1]+arr[2][2];
                                                dj[1] = arr[0][2]+arr[1][1]+arr[2][0];

                                                if(Tiaojian_2(h,l,dj))
                                                 {
                    for(int i = 0;i < 3;i++)
                    {
                         for(int j = 0;j < 3;j++)
                        {
                            printf("%d ",arr[i][j]);
                        }
                        printf("\n");
                    }
                     printf("\n\n");
                }

                                            }

                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    return 0;

}

这个方法的时间复杂度太大,代码也没有优化,把所有情况打印完毕计算机要运行5分钟左右。第一次体会到跑代码的快感。

方法二代码如下:
void Magic_teacher_3()
{
#define ROW 3
#define COL 3
    int arr[ROW][COL] = {0};//将arr全部元素置零
    int row = 0;
    int col = COL/2;
    arr[row][col] = 1;//将1放在第一行的中间
    for(int i = 2;i <= ROW*COL;i++)//2.后面的数字放在当前数字的的上一行后一列 
                                   //3.如果当前位置有数据,就放在前一个数字的下一行同列
    {
        row--;//上一行
        if(row < 0)//如果行为负数,把行置为最后一行
        {
            row += ROW;
        }
        col++;//下一列
        if(col > COL-1)//如果列大于最高列,把col置为第一列
        {
            col = COL - col;
        }

        if(arr[row][col] != 0)//如果当前位置有数据,放到前一数字的下一行同列
        {
            row = (row + 2) % ROW;
            col = (col-1+COL) %COL;
        }

        arr[row][col] = i;
    }

    for(int i= 0;i < ROW;i++)//打印魔方阵
    {
        for(int j = 0;j < COL;j++)
        {
            printf("%-3d",arr[i][j]);
        }
        printf("\n");

    }

}
二:4阶魔方阵(同8阶算法类似)
这里也用两种方法实现。
方法一:

void MagicCube_4()//4阶魔方阵
{
#define N 4
    int arr[N ][N ];
    int m = 1;
    for(int i = 0;i < N;i++)
    {
        for(int j = 0;j < 4;j++)
        {
            arr[i][j] = m++;
        }
    
    }
    int Firstnum = arr[N-1][N-1];
    //主对角线清零
    for(int i= 0;i <N;i++)
    {
        for( int j = 0 ;j<N;j++)
        {
            if(i == j)
            {
                arr[i][j] = 0;
               }
        }
    }
    //副对角线清零
    for(int i = 0;i < N;i++)
    {
        for(int j = 0;j < N;j++)
        {
            if((i+j) == 3)
            {
                arr[i][j] = 0;
            }
        }
    }

    //对角线填数字 firstnum = 16;第一个数字为16
    for(int i = 0;i<N;i++)
    {
        for(int j = 0;j<N;j++)
        {
            if(arr[i][j] == 0)
            {
                arr[i][j] = Firstnum --;
            }
            else
            {
                Firstnum--;
            }
        }
    }

    //打印结果
    for(int i = 0;i< N;i++)
    {
        for(int j = 0;j<N;j++)
        {
            printf("%d     ",arr[i][j]);
        }
        printf("\n");
    }    
}

方法二:

这里的从右上至左下应该为: ((i+j)%4)!=3

代码如下:
void Magic_8()//8阶或者4阶魔方阵
{
#define ROW 8
    int arr[ROW][ROW];
    int tmp = 1;
    int tmp2 = ROW*ROW;

    for(int i=0;i<ROW;i++)
    {
        for(int j=0;j<ROW;j++)
        {
            if((i%4!=j%4) && ((i+j)%4!=3))
            {
                arr[i][j] = tmp;
            }
            else
            {
                arr[i][j] = tmp2;
            }
            tmp++;
            tmp2--;
        }
    }
    for(int i=0;i<ROW;i++)
    {
        for(int j=0;j<ROW;j++)
        {
            printf("%-4d",arr[i][j]);
        }
        printf("\n");
    }

    /*if(!Check(arr,ROW))//准备写一个检查函数,检查每行每列对角线的和是否相等。(待更新)
    {
        printf("不是魔方阵\n");
    }*/ 
}

猜你喜欢

转载自blog.csdn.net/zDavid_2018/article/details/81141787
今日推荐