Vijos P1228 拯救世界-星际大战
题目
描述
外星人逐渐逼近,为了保护地球,现在决定直接在外空进行战斗。
现在我们有N个导弹。需要在最短的时间内,用这N个导弹摧毁敌方n个目标(1个导弹只能摧毁1个目标)。N个导弹和目标的位置不一定相同,但是给每个导弹确定目标是一件很麻烦的事情。请你编程帮助给每个导弹确定目标,使每个导弹到其目标的距离之和最小。
格式
输入格式
第一行输入N(N<=20)
接下来N行每行包含一个坐标(x,y),表示一个导弹,-10000
1
10 1
6 -1
样例输出1
4.472
题解
状压DP
f[i][j]表示枚举到第i个导弹,j表示目标的状态
(自己写的状压DP有点小问题。。。LYF大佬帮我A了此题)
代码
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int n;
double ans;
double x[25],y[25],a[25],b[25],f[25][1<<20];
double min(double x,double y){return x<y?x:y;}
double dist(double x,double y,double a,double b){return sqrt((x-a)*(x-a)+(y-b)*(y-b));}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]);
for (int i=0;i<n;i++) scanf("%lf%lf",&a[i],&b[i]);
for (int i=1;i<(1<<n);i++) for (int j=1;j<=n;j++) f[j][i]=1e9;
f[0][0]=0;
for (int i=0;i<(1<<n);i++)
for(int j=1;j<=n;j++)
for (int k=0;k<n;k++)
{
int w=(i|(1<<k));
if (w==i) continue;
f[j][w]=min(f[j][w],f[j-1][i]+dist(x[j],y[j],a[k],b[k]));
}
printf("%.3lf",f[n][(1<<n)-1]);
return 0;
}