状态压缩DP
主要是由于每次从最右边的1开始找,所以一般的正推可能会导致产生很多冗余状态
记忆话搜索的话会好不少
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int n;
struct Point
{
double x, y;
double dis;
}node[21];
double f[1<<20];
double map[21][21];
double dist(int i, int j)
{
return sqrt((node[i].x - node[j].x) * (node[i].x - node[j].x)
+ (node[i].y - node[j].y) * (node[i].y - node[j].y));
}
double dp(int depth)
{
if(f[depth] >= 0) return f[depth];
int val = depth;
int pos = -1;
f[depth] = 1e12;//初始化为正无穷
for(int i = 0; val; val >>= 1, i++)
{
if(val & 1)
{
if(pos == -1) pos = i;
else
{
f[depth] = min(f[depth], dp(depth - (1 << pos) - (1 << i))
+ node[pos].dis + map[pos][i]);
f[depth] = min(f[depth], dp(depth - (1 << pos) - (1 << i))
+ node[i].dis + map[pos][i]);
}
}
}
return f[depth];
}
int main()
{
int cas = 1;
int T;
double sx, sy;
scanf("%d", &T);
while(T--)
{
scanf("%lf%lf", &sx, &sy);
scanf("%d", &n);
n <<= 1;
for(int i = 0; i < n; i++)
scanf("%lf%lf", &node[i].x, &node[i].y);
node[n].x = sx;
node[n].y = sy;
for(int i = 0; i < n; i++)
node[i].dis = dist(i,n);
for(int i = 0; i < n; i++)
for(int j = i + 1; j < n; j++)
map[i][j] = map[j][i] = dist(i,j);
int st = 1 << n;
for(int i = 0; i < st; i++) f[i] = -1;
f[0] = 0.0;
printf("Case #%d: %0.2lf\n",cas++,dp((st-1)));
}
return 0;
}