枚举各种情况下的周长,然后dp求出最小值。
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<vector>
using namespace std;
struct point
{
int x;
int y;
}points[1100];
double dp[1<<9];
double d[1<<9];
int n;
int N;
double ans;
int crossmulty(point a, point b, point c)
{
return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}
int cmp(const void *a, const void *b)
{
if((*(point*)a).y==(*(point*)b).y) return (*(point*)a).x-(*(point*)b).x;
return (*(point*)a).y-(*(point*)b).y;
}
double Distance(point a, point b)
{
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double Graham()
{
double sum=0;
int top=1,stack[1100];
stack[0]=0, stack[1]=1;
for(int i=0;i<n;i++)
{
while(top>=1 and crossmulty(points[i], points[stack[top]], points[stack[top-1]])>=0)
{
top--;
}
stack[++top]=i;
}
stack[++top]=n-2;
int temp=top;
for(int i=n-1;i>=0;i--)
{
while(top>=temp and crossmulty(points[i], points[stack[top]], points[stack[top-1]])>=0)
{
top--;
}
stack[++top]=i;
}
for(int i=0;i<top;i++)
{
sum+=Distance(points[stack[i]],points[stack[i+1]]);
}
return sum;
}
point p[1100];
int main()
{
double r;
int cas=1;
double dis;
while(scanf("%d%lf",&N,&r)&&N+r)
{
for(int i=0;i<N;i++)
scanf("%d%d",&p[i].x,&p[i].y);
for(int i=1;i<(1<<N);i++)
{
int t=i;
int k=0;
n=0;
while(t)
{
if(t&1)
points[n++]=p[k];
k++;
t>>=1;
}
qsort(points,n,sizeof(*points),cmp);
dis=2*r*3.1415926;
dis+=Graham();
d[i]=dis;
}
ans=1000001;
for(int set = 1; set < (1 << N); ++set)
{
dp[set] = 1000001;
for (int subset = set; subset > 0; (--subset) &= set)
dp[set]=min(dp[set],dp[set-subset]+d[subset]);
}
printf("Case %d: length = %.2lf\n",cas++,dp[(1 << N)-1]);
}
return 0;
}