题目链接:点击打开链接
9 12 7 24 9 30 5 41 9 80 7 50 87 22 9 45 1 50 7 0
243.06
题意:有很多棵树,求一根最短的绳子,绑在某些树上,能使所有树都在绳子内。
思路:明显的凸包模板,只是这道题十分坑。n==1和n==2要特判,因为一般凸包题都是从3开始的。但这道题没有说明,而且也确实有n==2的数据。
注意用的是绳子n==2的时候不需要乘以二,只要在两颗树上绑一根绳子便好。已经能满足两颗树都在绳子内的要求。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define eps 1e-8 #define N 110 struct Node { double x,y; }p[N],stack[N]; double mulit(Node a,Node b,Node c) { return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } double dist(Node a,Node b) { return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } int cmp(Node a,Node b) { if(mulit(p[0],a,b)>0) return 1; if(mulit(p[0],b,a)==0&&(dist(p[0],b)-dist(p[0],a))<eps) return 1; return 0; } int Graham(int n) { sort(p+1,p+n,cmp); stack[0]=p[0]; stack[1]=p[1]; stack[2]=p[2]; int top=2; for(int i=3;i<n;i++) { while(top>=1&&mulit(stack[top-1],p[i],stack[top])>=0) top--; stack[++top]=p[i]; } return top; } int main() { int n; while(~scanf("%d",&n)&&n) { for(int i=0;i<n;i++) scanf("%lf %lf",&p[i].x,&p[i].y); if(n==1) { printf("0.00\n"); continue; } if(n==2) { printf("%.2lf\n",sqrt(dist(p[0],p[1]))); continue; } int k=0; for(int i=0;i<n;i++) { if(p[k].y>p[i].y||(p[k].y==p[i].y&&p[k].x>p[i].x)) k=i; } swap(p[0],p[k]); int top=Graham(n); double sum=0.0; for(int i=1;i<=top;i++) sum+=sqrt(dist(stack[i],stack[i-1])); sum+=sqrt(dist(stack[0],stack[top])); printf("%.2lf\n",sum); } return 0; }