Codeforces Beta Round 8 C

发布时间 2023-12-04 16:48:45作者: ycllz

提炼
首先看到24
那无疑是状态压缩
这样我们dp[1<<24]就是 收集到state状态的min
关于转移 我们需要枚举当前状态下的两个0位 复杂度显然是2424(1<<24)级别的 虽然有剪枝
但是 我们仔细一想 我们的答案 不需要 任何的顺序 证明我们可以随便拿出最优的一组即可
我们找到第一个0位 这个位置显然要和其他配对 并且肯定有最优的一组
然后我们break即可 这样复杂度就是24*(1《24)

int dp[1<<24],pre[1<<24];
int dis[25][25];
int dist(PII A,PII B){return (A.first-B.first)*(A.first-B.first)+(A.second-B.second)*(A.second-B.second);}
void solve() {
    PII C;
    cin >> C.first >> C.second;
    int n;
    cin >> n;
    vector<PII > a(n + 1);
    a[n] = C;
    for (int i = 0; i < n; i++) {
        cin >> a[i].first >> a[i].second;
    }
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= n; j++) {
            dis[i][j] = dist(a[i], a[j]);
        }
    }
    memset(dp, 0x3f, sizeof dp);
    dp[0] = 0;
    for (int i = 0 ; i < (1<<n); i++) {
        if (dp[i] == 0x3f3f3f3f)continue;
        for (int j = 0; j < n; j++) {
            if (i >> j & 1)continue;
            for (int k = j; k < n; k++) {
                if (i >> k & 1)continue;
                int w = dis[j][k] + dis[j][n] + dis[n][k];
                if (dp[i | (1 << j) | (1 << k)] > dp[i] + w) {
                    dp[i | (1 << j) | (1 << k)] = dp[i] + w;
                    pre[i | (1 << j) | (1 << k)] = i;
                }
            }
            break; //zhongdian 
        }
    }
    cout << dp[(1 << n) - 1] << endl;
    int y = (1 << n) - 1;
    vector<int> ans;
    while (y) {
        auto ny = pre[y];
        ans.push_back(0);
        for (int i = 0; i < n; i++) {
            if (!(ny >> i & 1) && (y >> i & 1)) {
                ans.push_back(i + 1);
            }
        }
        y = ny;
    }
    ans.push_back(0);
    reverse(all(ans));
    for (auto i: ans)cout << i << ' ';
}