dfs+状态压缩剪枝,WA了一个点,求大佬调调
查看原帖
dfs+状态压缩剪枝,WA了一个点,求大佬调调
607834
yangCode01楼主2022/11/3 11:13
#include <bits/stdc++.h>

using namespace std;

int n;
double x, y;
double ans = 10000000;
vector<pair<double, double>> v;
double vis[20];
//状态记录 d[12][42501] 表示走到编号为12的点,所经过的点的编号为42501二进制序列为1的数
double f[20][33000];

//编号v1 v2的两个点的距离
double getDis(int v1, int v2) {
    return sqrt((v[v1].first - v[v2].first) * (v[v1].first - v[v2].first) +
                (v[v1].second - v[v2].second) * (v[v1].second - v[v2].second));
}

//lastid:上一个坐标的编号,status为当前走过的点编号组成的二进制序列的十进制值
void dfs(int u, int lastid, int status, double dis) {
    //剪枝
    if (dis >= ans)
        return;
    if (u == n) {
        ans = min(ans, dis);
        return;
    }
    for (int i = 1; i <= n; i++) {
        //更新状态,因为加上了i这个点,status + 2^i(1左移i位就是2的i的值)
        int newStatus = status + (1 << i);

        if (!vis[i]) {
            //状态压缩剪枝
            if (f[i][newStatus] != 0 && f[i][newStatus] <= f[lastid][status] + getDis(lastid, i))
                return;
            f[i][newStatus] = f[lastid][status] + getDis(lastid, i);
            vis[i] = 1;
            dfs(u + 1, i, newStatus, dis + getDis(lastid, i));
            vis[i] = 0;
        }
    }
}

int main() {
    cin >> n;
    v.push_back({0, 0});
    for (int i = 0; i < n; i++) {
        cin >> x >> y;
        v.push_back({x, y});
    }
    dfs(0, 0, 0, 0);
    printf("%.2lf", ans);
    return 0;
}



2022/11/3 11:13
加载中...