【CodeVS3201】奶牛代理商 XI

来源:互联网 发布:淘宝团队管理有什么用 编辑:程序博客网 时间:2024/06/03 02:55

【Description】

  小徐是USACO中国区的奶牛代理商,专门销售质优价廉的“FJ”牌奶牛。
  有一天,她正在卖奶牛,突然觉得很孤单,想把她的朋友接来。
可这要花一大笔钱。
  她有N个牛棚,想让你帮她重新围一块地,包含所有牛棚,且是凸多边形(否则奶牛会撞墙角)
  她现在经济很困难,不用你关心省下的地能卖多少钱,只要能让围栏最短,花最少的钱。
  请你计算围栏的最短长度。


【Input】

  N
  每个牛棚的坐标(整数)


【Output】

  最短长度(保留2位小数)


【Sample Input】

40 33 00 01 1

【Sample Output】

10.24

【Data Size and Hint】

  N1000
  |X|,|Y|500


【Solution】

  题目是形象地告诉你求一个能包进所有点的凸包周长。
  具体方法参考LRJ黑书上的叉积部分和白书上Andrew算法部分。
  参考代码如下:
  

type point = record               x,y:longint;             end;var n,m,i:longint;    ans:double;    p:array[0..1010] of point;    stack:array[0..1010] of point;procedure init; //读入  var i:longint;  begin    readln(n);    for i:=1 to n do readln(p[i].x,p[i].y);  end;procedure qsort(l,r:longint);  //按x第一关键字,y第二关键字排序  var i,j,mid,mid2:longint;      tmp:point;  begin    i:=l; j:=r; mid:=p[(i+j) shr 1].x; mid2:=p[(i+j) shr 1].y;    repeat      while (p[i].x<mid) or ((p[i].x=mid) and (p[i].y<mid2)) do inc(i);      while (p[j].x>mid) or ((p[j].x=mid) and (p[j].y>mid2)) do dec(j);      if i<=j then begin        tmp:=p[i]; p[i]:=p[j]; p[j]:=tmp;        inc(i); dec(j);      end;    until i>j;    if i<r then qsort(i,r);    if l<j then qsort(l,j);  end;function Cross(a,b:point):longint;  //求叉积  begin    exit(a.x*b.y-b.x*a.y);  end;function minus(a,b:point):point;  //求向量差  begin    minus.x:=a.x-b.x; minus.y:=a.y-b.y;  end;procedure ConvexHull;  //Andrew求凸包  var i,k:longint;  begin    m:=1;    fillchar(stack,sizeof(stack),0);    for i:=1 to n do begin      while (m>2) and (Cross(minus(stack[m-1],stack[m-2]),                             minus(p[i],stack[m-2]))<=0)        do dec(m);      stack[m]:=p[i]; inc(m);    end;    k:=m;    for i:=n-1 downto 1 do begin      while (m>k) and (Cross(minus(stack[m-1],stack[m-2]),                             minus(p[i],stack[m-2]))<=0)        do dec(m);      stack[m]:=p[i]; inc(m);    end;  end;function calc(a,b:point):double;  //计算两点间距离  begin    exit(sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)));  end;procedure print;  //输出周长  var i:longint;  begin    for i:=2 to m-1 do      ans:=ans+calc(stack[i],stack[i-1]);    writeln(ans:0:2);  end;begin  init;  qsort(1,n);  ConvexHull;  print;end.
0 0
原创粉丝点击