2 0 0 1 6 0 3 0 0 0 2 1 0 2 1 -1 0 -2 0
Case #1: 6.00 Case #2: 4.41
题意:
给出初始坐标,还有目标坐标,一次能射击两个坐标,求路程最短为多少
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
#define exp 1e-8
struct node
{
double x,y;
} o,s[50];
int n;
double d[50][50],dp[(1<<20)+1],os[50];
double dis(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int cmp(node a,node b)
{
return dis(a,o)<dis(b,o);
}
double dfs(int u)
{
if(dp[u]>exp) return dp[u];
if(!u) return 0;
int m = 0;
while(!(u&(1<<m))) m++;
int tem;
for(int i = m+1; i<n; i++)
{
if(u&(1<<i))
{
tem = u - (1<<i) - (1<<m);
double ans = dfs(tem)+os[m]+d[i][m];
if(dp[u]<exp || ans<dp[u])
dp[u] = ans;
}
}
return dp[u]<exp?0:dp[u];
}
int main()
{
int t,i,j,k,cas = 1;
scanf("%d",&t);
while(t--)
{
scanf("%lf%lf%d",&o.x,&o.y,&n);
n*=2;
for(i = 0; i<n; i++)
scanf("%lf%lf",&s[i].x,&s[i].y);
sort(s,s+n,cmp);
for(i = 0; i<n; i++)
for(j = 0; j<n; j++)
{
d[i][j] = dis(s[i],s[j]);
}
for(i = 0; i<n; i++)
os[i] = dis(o,s[i]);
for(i = 0; i<(1<<n); i++)
dp[i] = -1.0;
dfs(i-1);
printf("Case #%d: %.2f\n",cas++,dp[i-1]);
}
return 0;
}
HDU3920:Clear All of Them I(状态压缩),布布扣,bubuko.com
HDU3920:Clear All of Them I(状态压缩)
原文:http://blog.csdn.net/libin56842/article/details/25652139