제출 #1194181

#제출 시각아이디문제언어결과실행 시간메모리
1194181LucaIlieOlympiads (BOI19_olympiads)C++17
100 / 100
1905 ms247996 KiB
#include <bits/stdc++.h>
using namespace std;
using ull = unsigned long long;

#if defined(__GNUC__)
#pragma GCC optimize("Ofast,unroll-loops,inline,fast-math")
#pragma GCC target("sse4.2,avx,avx2,bmi,bmi2,popcnt")
#pragma GCC optimize("no-stack-protector")
#endif

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, K;
    long long C;
    cin >> N >> K >> C;
    vector<vector<int>> score(N, vector<int>(K));
    for (int i = 0; i < N; i++)
        for (int j = 0; j < K; j++)
            cin >> score[i][j];

    // precompute powers of N for encoding
    vector<ull> powN(K, 1);
    for (int i = 1; i < K; i++)
        powN[i] = powN[i - 1] * (ull)N;

    // 1) greedy “best” K‐set: one highest‐scoring unused contestant per event
    vector<bool> used(N, false);
    vector<int> startTeam;
    startTeam.reserve(K);
    for (int e = 0; e < K; e++) {
        int bestJ = 0, bestSc = -1;
        for (int j = 0; j < N; j++) {
            if (!used[j] && score[j][e] > bestSc) {
                bestSc = score[j][e];
                bestJ = j;
            }
        }
        used[bestJ] = true;
        startTeam.push_back(bestJ);
    }
    sort(startTeam.begin(), startTeam.end());

    auto encode = [&](const vector<int>& T) {
        ull s = 0;
        for (int i = 0; i < K; i++)
            s += (ull)T[i] * powN[i];
        return s;
    };
    auto fullScore = [&](const vector<int>& T) {
        int tot = 0;
        for (int e = 0; e < K; e++) {
            int m = 0;
            for (int x: T)
                m = max(m, score[x][e]);
            tot += m;
        }
        return tot;
    };

    struct Node {
        ull st;
        int sc;
    };
    struct Cmp {
        bool operator()(Node const& a, Node const& b) const {
            return a.sc < b.sc;
        }
    };

    priority_queue<Node, vector<Node>, Cmp> pq;
    unordered_set<ull> vis;
    vis.reserve((size_t)C * K + 10);

    ull s0 = encode(startTeam);
    pq.push({s0, fullScore(startTeam)});
    vis.insert(s0);

    vector<int> cur(K), newt(K);
    vector<int> base(K - 1), baseMax(K);
    bitset<500> in;

    // 2) best-first: pop best, expand all Hamming‐1 neighbors, repeat C–1 times
    for (long long iter = 1; iter < C; iter++) {
        auto [st, sc] = pq.top();
        pq.pop();

        // decode st → cur[]
        {
            ull x = st;
            for (int i = 0; i < K; i++) {
                cur[i] = int(x % (ull)N);
                x /= (ull)N;
            }
        }

        // for each position to remove
        for (int rem = 0; rem < K; rem++) {
            // build base[0..K-2]
            int t = 0;
            for (int i = 0; i < K; i++) {
                if (i == rem) continue;
                base[t++] = cur[i];
            }
            sort(base.begin(), base.end());

            // compute per-event max over those K-1 guys
            fill(baseMax.begin(), baseMax.end(), 0);
            for (int x: base)
                for (int e = 0; e < K; e++)
                    baseMax[e] = max(baseMax[e], score[x][e]);
            int baseScore = accumulate(baseMax.begin(), baseMax.end(), 0);

            // mark which are in the K-1 base
            in.reset();
            for (int x: base)
                in.set(x);

            // try every j not in that base
            for (int j = 0; j < N; j++) {
                if (in.test(j)) continue;

                // delta of adding j
                int delta = 0;
                for (int e = 0; e < K; e++) {
                    int sje = score[j][e];
                    if (sje > baseMax[e])
                        delta += sje - baseMax[e];
                }

                // build newt = sorted insertion of j into base[ ]
                bool done = false;
                int p = 0, q = 0;
                while (p < K) {
                    if (!done && (q == K - 1 || j < base[q])) {
                        newt[p++] = j;
                        done = true;
                    } else {
                        newt[p++] = base[q++];
                    }
                }

                // encode & push if unseen
                ull nst = 0;
                for (int i = 0; i < K; i++)
                    nst += (ull)newt[i] * powN[i];
                if (vis.insert(nst).second)
                    pq.push({nst, baseScore + delta});
            }
        }
    }

    // now the top of pq is the C-th best
    cout << pq.top().sc << "\n";
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...