快轉到主要內容

CSES-1070 Permutations

標籤: 建構
目錄

題目連結:https://cses.fi/problemset/task/1070


題意
#

題目會給我們一個正整數 \( n \),我們需要構造出一個包含 1 到 \( n \) 的數字排列。
這個排列有一個嚴格的要求:「任何兩個相鄰的數字,它們的差值絕對不能剛好是 1」。
如果不管怎麼排都做不到,就要輸出 NO SOLUTION

思路
#

這題的核心概念其實就是「分組」。我們只要把 1 到 \( n \) 的數字切成「偶數」和「奇數」這兩堆就好。

既然同一組的數字都是奇數或都是偶數,那麼它們彼此之間的差值至少都會是 2,完全不用擔心會相差 1 的問題。
也就是說,我們只要先把所有的偶數印出來,再把所有的奇數接著印在後面,這兩堆內部各自的相鄰規則就完美解決了。

唯一有危險的地方,只有「最後一個偶數」跟「第一個奇數」的這個交界處。
不過想一下就會發現,只要 \( n \ge 4 \),這個交界的差距絕對大於 1。但如果是 \( n = 2 \) 或 \( n = 3 \),數字實在太少,怎麼閃都會撞在一起,所以這兩種情況直接當成無解來處理。至於 \( n = 1 \) 呢?因為只有一個數字,不跟任何人相鄰,所以也是合法的一種。

程式碼
#

#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define fi first
#define se second
#define INF LONG_LONG_MAX/1000
#define WA() cin.tie(0)->sync_with_stdio(0)
#define all(x) (x).begin(), (x).end()
#define int long long
#define PII pair<int, int>

signed main() { WA();
    int n;
    cin >> n; // 讀取排列長度 n
    
    // 根據觀察,只有 n=2 或 n=3 時無法構造合法排列,直接輸出無解
    if (n == 2 || n == 3) return cout << "NO SOLUTION", 0;
    
    // 先依序印出所有偶數,確保偶數之間的差值至少為 2
    for (int i = 2; i <= n; i += 2) cout << i << ' ';
    
    // 接著依序印出所有奇數,確保奇數之間的差值也至少為 2
    // 並且連接處(最大的偶數與 1)的差值在 n >= 4 時一定會大於 1
    for (int i = 1; i <= n; i += 2) cout << i << ' ';
}
Piau 的筆記本
作者
Piau 的筆記本
希望我寫下來的東西能夠長久的記在我的腦中