CF8C Looking for Order(状压DP)

题意:

给出平面上的一些点,点之间的距离是欧几里得距离的平方。

女孩从起点开始,目标是把所有的点上的物品运送回起点,规定手上不能同时携带两个物品。

询问最快的时间和路线。

题解:

#include<bits/stdc++.h>
using namespace std;
const int maxn=30;
int dp[1<<24];
int pre[1<<24];
int g[maxn][maxn];
int x[maxn];
int y[maxn];
int n;
int dfs1 (int u) {
    if (dp[u]!=-1) return dp[u];
    dp[u]=1e9;
    for (int i=0;i<n;i++) {
        if (u&(1<<i)) {
            int nxt=dfs1(u^(1<<i));
            if (dp[u]>nxt+g[n][i]+g[i][n]) {
                dp[u]=nxt+g[n][i]+g[i][n];
                pre[u]=u^(1<<i);
            }
            for (int j=i+1;j<n;j++) {
                if (u&(1<<j)) {
                    nxt=dfs1(u^(1<<i)^(1<<j));
                    if (dp[u]>nxt+g[n][i]+g[i][j]+g[j][n]) {
                        dp[u]=nxt+g[n][i]+g[i][j]+g[j][n];
                        pre[u]=u^(1<<i)^(1<<j);
                    }
                }
            }
            break;
        }
    }
    return dp[u];
}
int dfs2 (int u) {
    if (u) {
        for (int i=0;i<n;i++) {
            if ((u^pre[u])&(1<<i))
                cout<<i+1<<" ";
        }
        cout<<"0 ";
        dfs2(pre[u]);
    }
}
void solve () {
    int X,Y;
    cin>>X>>Y>>n;
    x[n]=X;
    y[n]=Y;
    for (int i=0;i<n;i++) cin>>x[i]>>y[i];
    for (int i=0;i<=n;i++)
        for (int j=0;j<=n;j++) 
            g[i][j]=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
    memset(dp,-1,sizeof(dp));
    dp[0]=0;
    cout<<dfs1((1<<n)-1)<<'\n';
    cout<<"0 ";
    dfs2((1<<n)-1);
    
}
int main () {
    solve();
}

 

posted @ 2020-09-09 21:18  zlc0405  阅读(216)  评论(0编辑  收藏  举报