模板题,dp数组下标表示当前状态,拿物品的顺序无所谓,所以从最低位没拿的开始拿,是否顺路拿第二个或者不拿有24种状态。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 25
#define INF 1000000000
int x0,y0;
int n;
struct CO {
int x;
int y;
}a[30],a0;
int dp[1 << N];
int low[1 << N];
int pre[1 << N];
void yuch(){
low[0] = 1;
for(int i = 0; i < (1 << n); i++){
low[i] = ((i&1) == 0 ? 1 : (low[i >> 1] + 1));
}
}
int dis(CO a, CO b){
int ans = 0;
return ans = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
int main() {
scanf("%d %d",&x0,&y0);
a0.x = x0;
a0.y = y0;
scanf("%d",&n);
yuch();
for(int i = 0; i < n; i++){
scanf("%d%d", &a[i].x, &a[i].y);
}
for(int i = 0; i < (1<<n); i++){
dp[i] = INF;
pre[i] = 0;
}
dp[0] = 0;
for(int i = 0; i < (1 << n) - 1; i++){
for(int j = 0; j < n; j++){
if(j == low[i] - 1){//只拿一个
if((i & (1 << (low[i] - 1))) != 0)continue;
dp[i + (1 << (low[i] - 1))] = min(dp[i] + dis(a[low[i] - 1],a0) * 2, dp[i + (1 << (low[i]-1))]);
if(dp[i + (1 << (low[i] - 1))] == dp[i] + dis(a[low[i] - 1],a0) * 2){
pre[i + (1 << (low[i] - 1))] = i;
}
}
else {//两个
if(((i & (1 << j)) != 0) || ((i & (1 <<(low[i] - 1))) != 0))continue;
dp[i + (1 << (low[i] - 1)) +(1 << j)] = min(dp[i] + dis(a[low[i] - 1], a0) + dis(a[low[i] - 1], a[j]) + dis(a[j], a0) , dp[i + (1 << (low[i]-1)) +(1 << j)]);
if(dp[i + (1 << (low[i] - 1)) +(1 << j)] == dp[i] + dis(a[low[i] - 1], a0) + dis(a[low[i] - 1], a[j]) + dis(a[j], a0)){
pre[i + (1 << (low[i] - 1)) +(1 << j)] = i;
}
}
}
}
int pro[30];
int ind = (1 << n) - 1;
int fs = 1;
pro[0] = ind;
while(pre[ind] != 0){
pro[fs++] = pre[ind];
ind = pre[ind];
}
pro[fs] = 0;
printf("%d\n0 ",dp[(1 << n) - 1]);
for(int i = fs; i > 0 ; i--){
for(int j = 0; j < n; j++){
if((((1 << j) & pro[i]) == 0) && (((1 << j) & pro[i - 1]) != 0))printf("%d ",j + 1);
}
printf("0 ");
}
printf("\n");
return 0;
}