给n个物品的坐标, 和一个包裹的位置, 包裹不能移动。 每次最多可以拿两个物品, 然后将它们放到包里, 求将所有物品放到包里所需走的最小路程。
直接状压dp就好了。
#include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include <string> #include <queue> #include <stack> #include <bitset> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<1 #define mem(a) memset(a, 0, sizeof(a)) #define rson m+1, r, rt<<1|1 #define mem1(a) memset(a, -1, sizeof(a)) #define mem2(a) memset(a, 0x3f, sizeof(a)) #define rep(i, n, a) for(int i = a; i<n; i++) #define fi first #define se second typedef pair<int, int> pll; const double PI = acos(-1.0); const double eps = 1e-8; const int mod = 1e9+7; const int inf = 1061109567; const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; int n; int dp[1<<24], dis[25][25], b[1<<24], ans[500], cnt; pll a[25]; int main() { int x, y; cin>>a[0].fi>>a[0].se; cin>>n; a[n] = a[0]; for(int i = 0; i<n; i++) { scanf("%d%d", &a[i].fi, &a[i].se); } for(int i = 0; i<=n; i++) { for(int j = 0; j<=n; j++) { dis[i][j] = (a[i].fi-a[j].fi)*(a[i].fi-a[j].fi)+(a[i].se-a[j].se)*(a[i].se-a[j].se); } } mem2(dp); dp[0] = 0; for(int i = 0; i<(1<<n); i++) { if(dp[i]==inf) continue; for(int j = 0; j<n; j++) { if((1<<j&i)==0) { for(int k = j; k<n; k++) { if((1<<k&i)==0) { int tmp = i|(1<<j)|(1<<k); int d = dis[j][k]+dis[n][j]+dis[n][k]; if(dp[tmp]>dp[i]+d) { dp[tmp] = dp[i]+d; b[tmp] = i; } } } break; } } } cout<<dp[(1<<n)-1]<<endl; for(int i = (1<<n)-1; i!=0; i = b[i]) { int tmp = b[i]^i; ans[cnt++] = 0; for(int j = 0; j<n; j++) { if((1<<j)&tmp) { ans[cnt++] = j+1; } } } ans[cnt++] = 0; for(int i = cnt-1; i>=0; i--) { printf("%d ", ans[i]); } return 0; }