在 n×n 棋盤上放置 n 個皇後,使任意兩個皇後不在同行、同列、同對角線。輸出任意一組解(列號表示行位置)。n ∈ [8, 300],多測試用例。
N 皇後問題在 n ≥ 4 時總有解。根據 n mod 6 分類構造:
設 k = n/2(n 偶)或 k = (n-1)/2(n 奇)。根據 k 奇偶分四種子情況,構造四段序列拼接:
// 以 n mod 6 = 2, n 偶, k 偶為例 [k, k+2, ..., n], [2, 4, ..., k-2], [k+3, k+5, ..., n-1], [1, 3, ..., k+1]
完整分支見代碼。
#includeusing namespace std; int main() { int n; while (cin >> n, n) { if (n % 6 != 2 && n % 6 != 3) { if (n % 2 == 0) { // 偶數 for (int i = 2; i <= n; i += 2) cout << i << ' '; for (int i = 1; i <= n-1; i += 2) cout << i << ' '; } else { // 奇數 for (int i = 2; i <= n-1; i += 2) cout << i << ' '; for (int i = 1; i <= n; i += 2) cout << i << ' '; } } else { if (n % 2 == 0) { // n 偶數 int k = n / 2; if (k % 2 == 0) { // k 偶數 for (int i = k; i <= n; i += 2) cout << i << ' '; for (int i = 2; i <= k-2; i += 2) cout << i << ' '; for (int i = k+3; i <= n-1; i += 2) cout << i << ' '; for (int i = 1; i <= k+1; i += 2) cout << i << ' '; } else { // k 奇數 for (int i = k; i <= n-1; i += 2) cout << i << ' '; for (int i = 1; i <= k-2; i += 2) cout << i << ' '; for (int i = k+3; i <= n; i += 2) cout << i << ' '; for (int i = 2; i <= k+1; i += 2) cout << i << ' '; } } else { // n 奇數 int k = (n - 1) / 2; if (k % 2 == 0) { // k 偶數 for (int i = k; i <= n-1; i += 2) cout << i << ' '; for (int i = 2; i <= k-2; i += 2) cout << i << ' '; for (int i = k+3; i <= n-2; i += 2) cout << i << ' '; for (int i = 1; i <= k+1; i += 2) cout << i << ' '; cout << n; } else { // k 奇數 for (int i = k; i <= n-2; i += 2) cout << i << ' '; for (int i = 1; i <= k-2; i += 2) cout << i << ' '; for (int i = k+3; i <= n-1; i += 2) cout << i << ' '; for (int i = 2; i <= k+1; i += 2) cout << i << ' '; cout << n; } } } cout << endl; } return 0; }
此構造法基於 Pauls (1874) 和 Ahrens (1910) 的數學證明,利用模 6 同餘類將棋盤分解為可安全放置皇後的模式。所有 n ≥ 4 除 n=2,3 外均有解,本題 n ≥ 8 保證有解。
此題展示了數學構造法在組合優化問題中的驚人威力,將 NP-hard 問題(一般情況)在特定約束下轉化為 O(1) 輸出。