25. CF-Half Queen Cover


题目链接:Half Queen Cover

很有趣的一个构造题。比赛的时候构造了一个小时也没做出来。

官方题解的解法非常巧妙。假设最后的答案是需要用 \(k\) 个棋子,在不考虑斜线的情况下控制了 \(a\) 行和 \(b\) 列,那么就会有 \(n-a\) 行和 \(n-b\) 列没有被控制。这些区域就需要用斜线来填充。注意到这些区域最多形成 \(n-a+n-b-1\) 条斜线,所以可以列出不等式:

\[a\le k\\ b\le k\\ n-a +n-b-1\le k \]

三个加起来,就是 \(2n-1\le 3k\),即 \(k= \lceil \frac{2n-1}{3}\rceil\)

然后就是方案的构造,注意到 \(n\equiv 2\pmod 3\) 的时候可以整除,此时一种方案是在左上角将棋子放成一条斜线,在右下角将棋子放成一条斜线,如下图所示,中间的部分用斜向的攻击范围来覆盖:

00100000
01000000
10000000
000xxx00
000xxx00
000xxx00
00000001
00000010

其他两种情况由于需要向上取整,只需要在边角处放棋子转化成 \(n-1\) 的情况再去填充即可。

#include 
using namespace std;
void solve() {
    int n;
    cin >> n;
    if (n <= 2) {
        cout << "1\n1 1" << endl;
        return;
    }
    int ans = 0, cnt = 0;
    while (n % 3 != 2) {
        n--;
        ans++, cnt++;
    }
    ans += 2 * (n / 3) + 1;
    cout << ans << endl;
    for (int i = 1; i <= cnt; ++i) {
        cout << n + i << ' ' << n + i << endl;
    }
    int k = n / 3;
    for (int i = 1; i < k + 2; ++i) {
        cout << i << ' ' << k + 2 - i << endl;
    }
    for (int i = n; i > n - k; --i) {
        cout << i << ' ' << 2 * n + 1 - k - i << endl;
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T = 1;
    // cin >> T;
    while (T--)
        solve();
}