求解N阶幻方

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <time.h>
#include <string.h>
#include <map>

using namespace std;

const int N = 1e2 + 10;

int arr[N][N];

int mod(int x, int m) {
  while (x > m)
    x -= m;
  return x;
}

void output(int n) {
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++)
      cout << arr[i][j] << "\t";
    cout << endl;
  }
  cout << endl;
}

bool check(int n) {
  int sum = n * (n * n + 1) / 2;
  cout << sum << endl;
  int sumleft = 0, sumright = 0;
  for (int i = 1; i <= n; i++) {
    sumleft += arr[i][i];
    sumright += arr[i][n - i + 1];
    int tmp1 = 0, tmp2 = 0;
    for (int j = 1; j <= n; j++) {
      tmp1 += arr[i][j];
      tmp2 += arr[j][i];
    }
    if (tmp1 != sum || tmp2 != sum)
      return false;
  }
  if (sumleft != sum || sumright != sum)
    return false;
  return true;
}

void change(int n, int sx, int sy) {
  int sum = (1 + n * n);
  int ex = sx + 3;
  int ey = sy + 3;
  arr[sx][sy] = sum - arr[sx][sy];
  arr[ex][ey] = sum - arr[ex][ey];
  arr[sx][ey] = sum - arr[sx][ey];
  arr[ex][sy] = sum - arr[ex][sy];
  sx++, sy++, ex--, ey--;
  arr[sx][sy] = sum - arr[sx][sy];
  arr[ex][ey] = sum - arr[ex][ey];
  arr[sx][ey] = sum - arr[sx][ey];
  arr[ex][sy] = sum - arr[ex][sy];
}

int rob(int sx, int sy, int n, int num) {
  int nx = sx, ny = sy + n / 2;
  for (int i = 0; i < n * n; i++) {
    arr[nx][ny] = num++;
    int tx = sx + mod((nx - 1) + n, n) - 1;
    int ty = sy + mod(ny + 1, n) - 1;
    if (arr[tx][ty] != 0) {
      nx = sx + mod(nx + 1, n) - 1;
    }
    else {
      nx = tx;
      ny = ty;
    }
  }
  return num;
}



int main() {
  int n;
  while (cin >> n) {
    memset(arr, 0, sizeof(arr));
    if (n & 1) {
      rob(1, 1, n, 1);
    }
    else {
      if (n % 4 == 0) {
        for (int i = 1; i <= n; i++)
          for (int j = 1; j <= n; j++)
            arr[i][j] = (i - 1) * n + j;
        for (int i = 1; i <= n; i += 4) 
          for (int j = 1; j <= n; j += 4)
            change(n, i, j);
      }
      else {
        int num = 1, k = (n - 2) / 4, m = n / 2;
        num = rob(1, 1, m, num);
        num = rob(1 + m, 1 + m, m, num);
        num = rob(1, 1 + m, m, num);
        num = rob(1 + m, 1, m, num);
        for (int i = 1; i <= m; i++) {
          for (int j = 1; j <= k; j++) {
            if (i != m / 2 + 1)
              swap(arr[i][j], arr[i + m][j]);
            else
              swap(arr[i][j + k], arr[i + m][j + k]);
          }
        }
        for (int i = 1; i <= m; i++) {
          for (int j = 0; j < k - 1; j++) {
            int nj = j + m + 1 + m / 2;
            swap(arr[i][nj], arr[i + m][nj]);
          }
        }
      }
    }
    output(n);
    if (check(n))
      puts("YES");
    else
      puts("NO");
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值