mayoko’s diary

プロコンとかいろいろ。

Codeforces Round #330 (Div. 1) C. Edo and Magnets

解法

各マグネットの中心(重心)座標しか興味ないので入力値からそれを求めます。この時, double で管理しようとすると不幸になるのですべての座標が 2 倍されてると考えて座標が整数になるようにしましょう。

この重心座標については, どう考えても毎回 左端/右端/上端/下端 のいずれかにある頂点を取り除いていくことが最適です。

ということで,  4^k 通りの取り除き方を試しながら頑張れば良いです。
これ k = 50 程度までなら解けますよね, 多分。( {}_k C_4通り調べれば良いので)

const ll INF = 1ll<<60;
const int MAXN = 100100;
ll ans = INF;
int n, k;
bool used[MAXN];
// 0:小さい順にx 1:大きい順にx 2:小さい順にy 3:大きい順にy
pair<ll, int> P[4][MAXN];

void dfs(int cnt) {
    if (cnt == k) {
        ll tmp[4];
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < n; j++) if (!used[P[i][j].second]) {
                tmp[i] = P[i][j].first;
                break;
            }
        }
        ll dx = tmp[1]-tmp[0];
        ll dy = tmp[3]-tmp[2];
        dx = (dx+1)/2;
        dy = (dy+1)/2;
        dx = max(dx, 1ll);
        dy = max(dy, 1ll);
        ans = min(ans, dx*dy);
        return;
    }
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < n; j++) {
            if (!used[P[i][j].second]) {
                used[P[i][j].second] = true;
                dfs(cnt+1);
                used[P[i][j].second] = false;
                break;
            }
        }
    }
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> n >> k;
    if (n <= k) {
        cout << 1 << endl;
        return 0;
    }
    for (int i = 0; i < n; i++) {
        ll x1, x2, y1, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        for (int j = 0; j < 2; j++) {
            P[j][i] = make_pair(x1+x2, i);
        }
        for (int j = 2; j < 4; j++) {
            P[j][i] = make_pair(y1+y2, i);
        }
    }
    for (int i = 0; i < 4; i++) sort(P[i], P[i]+n);
    reverse(P[1], P[1]+n);
    reverse(P[3], P[3]+n);
    dfs(0);
    cout << ans << endl;
    return 0;
}