1. 程式人生 > 其它 >幻方問題

幻方問題

問題描述

幻方是一種很神奇的 N*NN∗N 矩陣:它由數字 1,2,3,⋯⋯,N×N 構成,且每行、每列及兩條對角線上的數字之和都相同。
當 N 為奇數時,我們可以通過下方法構建一個幻方:
首先將 1寫在第一行的中間。

之後,按如下方式從小到大依次填寫每個數 K(K=2,3,⋯,N×N) :

  1. 若 (K-1)在第一行但不在最後一列,則將 K 填在最後一行, (K-1)所在列的右列;
  2. 若 (K-1)在最後一列但不在第一行,則將 K填在第一列, (K-1)所在行的上3一行;
  3. 若 (K-1)在第一行最後一列,則將 K填在 (K-1)的正下方;
  4. 若 (K-1)既不在第一行,也不在最後一列,如果 (K-1) 的右上方還未填數,則將 KK 填在 (K-1) 的右上方,否則將 K 填在 (K-1) 的正下方。

現給定 N ,請按上述方法構造 N×N 的幻方。

輸入格式

一個正整數 N ,即幻方的大小。

輸出格式

共 N行 ,每行 N個整數,即按上述方法構造出的 N×N 的幻方,相鄰兩個整數之間用單空格隔開。

當時看到這一題,稍微有點傻。因為這題就是一個模擬題,而且整個的模擬過程都已經告訴你了。但卻屬於普及題而非入門題,比較奇怪。但是該題暗藏玄機。

首先是直接模擬的程式碼

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long int ll;

ll magic_square[
40][40]; ll x[1600]; ll y[1600]; int main() { int N; cin >> N; magic_square[1][N / 2 + 1] = 1; x[1] = 1; y[1] = N / 2 + 1; for (int i = 2; i <= N * N; i++) { if (x[i - 1] == 1 && y[i - 1] != N) { magic_square[N][y[i - 1] + 1] = i; x[i] = N; y[i] = y[i - 1] + 1; } else if
(x[i - 1] != 1 && y[i - 1] == N) { magic_square[x[i - 1] - 1][1] = i; x[i] = x[i - 1] - 1; y[i] = 1; } else if (magic_square[1][N]==i-1) { magic_square[2][N] = i; x[i] = 2; y[i] = N; } else if (x[i - 1] != 1 && y[i - 1] != N) { if (magic_square[x[i - 1] - 1][y[i - 1] + 1] == 0) { magic_square[x[i - 1] - 1][y[i - 1] + 1] = i; x[i] = x[i - 1] - 1; y[i] = y[i - 1] + 1; } else { magic_square[x[i - 1] + 1][y[i - 1]] = i; x[i] = x[i - 1] + 1; y[i] = y[i - 1]; } } } for (int i = 1; i <= N; i++) { for (int j = 1; j <= N; j++) { cout << magic_square[i][j] << ' '; } cout << endl; } return 0; }

十分簡單粗暴

但這一題還有更簡便的解法。可以將題目分析一遍。以3階幻方為例
在這裡插入圖片描述
從1開始,將剩餘的數按一下次序放:

1. 如果“右上角”有數,則置於其正下方
2. 如果“右上角”沒有數,則置於其右上角

此處的“右上角”並非真正意義上的右上角,1位於第一行正中間,而第一行上面沒有行數,則放於最後一行,即所謂“上行”一行,而後右行一列,即到達所謂右上角,將2放於最後一行,最後一列。
2的右方沒有列,故放於第一列,再上行一行,將3置於第二行,第一列。

簡單來說:將整個幻方矩陣的每一個空位視為迴圈的

這樣一來就可以很大程度上簡化程式碼

#include <iostream>
using namespace std;

int n, ms[40][40], x, y;

int main() {
	cin >> n;
	x = 1, y = (n + 1) / 2;
	for (int i = 1; i <= n * n; i++) {
		ms[x][y] = i;
		if (!ms[(x - 2 + n) % n + 1][y % n + 1]) 
			x = (x - 2 + n) % n + 1, y = y % n + 1;
		else x = x % n + 1;
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cout << ms[i][j] << ' ';
		}
		cout << endl;
	}
}

執行結果

在這裡插入圖片描述

在這裡插入圖片描述