zoukankan      html  css  js  c++  java
  • 任意N阶幻方算法实现

    算法原理请参考:https://www.zhihu.com/question/23531676

    先定义一些通用的函数,比如创建空幻方,删除幻方,打印幻方。

    创建幻方

    int **NewMagicS(int n) {
        int **magic = new int*[n];
        for (int k = 0; k < n; k++)
            magic[k] = new int[n];
        return magic;
    }

    删除幻方

    void DeleteMagicS(int **magic, int n) {
        for (int k = 0; k < n; k++)
            delete[] magic[k];
        delete[] magic;
    }

    打印幻方

    void ShowMagicS(int **magic, int n) {
        int i, j;
        for (i = 0; i < n; i++) {
            for (j = 0; j < n; j++)
                printf("%-6d", magic[i][j]);
            printf("
    ");
        }
    }

    一、奇数幻方算法实现:

    辅助函数(实现算法)

    void OddMagicSA(int **magic, int n, int value) {
        int i, j, total;
        //初始化二维数组
        for (i = 0; i < n; i++)
            for (j = 0; j < n; j++)
                magic[i][j] = 0;
        i = 0;
        j = n / 2;
        magic[i][j] = value++;
        for (total = 1; total < n*n; total++, value++) {//向右上角移动
            //调整位置
            if (!magic[(i - 1) == -1 ? n - 1 - i : i - 1][(j + 1) % n]) { //空闲
                i = (i - 1) == -1 ? n - 1 - i : i - 1;
                j = (j + 1) % n;
            }
            else //原位置下移一格(行变)
                i = (i + 1) % n;
            magic[i][j] = value;
        }
    }

    主函数(负责打印)

    void OddMagicS(int n) {
        int **magic;
        if (n <= 0 || n == 1 || n == 2 || (n % 2 == 0)) return;
        magic = NewMagicS(n);
        OddMagicSA(magic, n, 1);
        //显示奇数幻方
        ShowMagicS(magic, n);
        DeleteMagicS(magic, n);
    }

    二、偶数幻方算法实现:

    辅助函数(算法实现)

    void EvenMagicSA(int **magic, int n, int value) {
        int i, j;
        //初始化二维数组
        for (i = 0; i < n; i++)
            for (j = 0; j < n; j++)
                magic[i][j] = 0;
        //分割为4x4格子,然后填充对角线位置为-1
        for (i = 0; i < n; i += 4)//i, j 表示4x4起点
            for (j = 0; j < n; j += 4) {
                //对角线填充
                for (int k = 0; k < 4; k++) {
                    magic[i + k][j + k] = -1;
                    magic[i + 3 - k][j + k] = -1;
                }
            }
        i = 0;
        for (; i < n; i++)
            for (j = 0; j < n; j++, value++) {
                //先填充4x4非对角线,从左向右,从上向下
                if (magic[i][j] != -1 && magic[i][j] == 0) magic[i][j] = value;
                //填充4x4对角线,左右向左,从下向上
                if (magic[n - 1 - i][n - 1 - j] == -1) magic[n - 1 - i][n - 1 - j] = value;
            }
    }

    主要函数(打印幻方)

    void EvenMagicS(int n) {
        int **magic;
        if (n <= 0 || n == 1 || n == 2 || n % 4 != 0) return;
        magic = NewMagicS(n);
        EvenMagicSA(magic, n, 1);
        //显示偶数幻方
        ShowMagicS(magic, n);
        DeleteMagicS(magic, n);
    }

    三、最后一个幻方类型叫做奇偶幻方,算法实现:

    增加一个幻方复制

    void CopyMagicS(int **dstMagic, int sLine, int sColumn, int **srcMagic, int n) {
        for (int i = sLine, p = 0; p < n; i++, p++)
            for (int j = sColumn, q = 0; q < n; j++, q++)
                dstMagic[i][j] = srcMagic[p][q];
    }

    主要函数(算法实现)

    void OddEvenMagicS(int n) {
        int **magic, **magicTemp, i, j, k, mid;
        if (!(n >= 0 && n != 1 && n != 2 && (n % 2 == 0 && n % 4 != 0))) return;
        magic = NewMagicS(n);
        magicTemp = NewMagicS(n / 2);
        //顺时针分成A,B,C,D四个象限,并且按照A, D, B, C的顺序以奇幻方方法填充
        i = j = 0;//A象限
        OddMagicSA(magicTemp, n / 2, 1);
        CopyMagicS(magic, i, j, magicTemp, n / 2);
        i = j = n / 2;//D象限
        OddMagicSA(magicTemp, n / 2, n / 2 * n / 2 + 1);
        CopyMagicS(magic, i, j, magicTemp, n / 2);
        i = 0;
        j = n / 2;//B象限
        OddMagicSA(magicTemp, n / 2, n / 2 * n / 2 * 2 + 1);
        CopyMagicS(magic, i, j, magicTemp, n / 2);
        i = n / 2;
        j = 0;//C象限
        OddMagicSA(magicTemp, n / 2, n / 2 * n / 2 * 3 + 1);
        CopyMagicS(magic, i, j, magicTemp, n / 2);
        k = (n - 2) / 4;
        //A, C象限交换
        for (int l = 0; l < n / 2; l++) 
            for (int m = 0; m < k; m++)
                if (l == n / 4) {//中间行
                    mid = magic[l][k + m];
                    magic[l][k + m] = magic[n / 2 + l][k + m];
                    magic[n / 2 + l][k + m] = mid;
                }
                else {
                    mid = magic[l][m];
                    magic[l][m] = magic[n / 2 + l][m];
                    magic[n / 2 + l][m] = mid;
                }
        //B, D象限交换
        for (int l = 0; l < k - 1; l++) {//
            for (int m = 0; m < n / 2; m++) {//
                mid = magic[m][3 * n / 4 - l];
                magic[m][3 * n / 4 - l] = magic[n / 2 + m][3 * n / 4 - l];
                magic[n / 2 + m][3 * n / 4 - l] = mid;
            }
        }
        //显示奇偶数幻方
        ShowMagicS(magic, n);
        DeleteMagicS(magic, n);
        DeleteMagicS(magicTemp, n / 2);
    }

    所有代码均经过测试,结果正确。

  • 相关阅读:
    怎么才能快捷的使用Beyond Compare
    Navicat遇到1130错误该如何处理
    做软件开发对这几款软件应该不陌生
    有什么方法可以快速找出文本的异同
    怎么给数据库管理工具设置数据同步
    程序员常常会用到的几款文本编辑器
    Java经典案例之-判断兔子的数量(斐波那契数列)
    菲波那切数列案例演示(递归方法)
    Java反射机制
    位运算,算术、逻辑运算详解-java篇
  • 原文地址:https://www.cnblogs.com/dalgleish/p/8845895.html
Copyright © 2011-2022 走看看