凸包
http://unbelievable.ycool.com/post.804688.html
呀呀.... 自学凸包呀...
知道1些基本操作....
知道1些基本操作....
| program prog3; const maxt = 1000; maxn = 1000; inf = 'wudi3.in'; ouf = 'wudi3.out'; type node = record x, y : longint; end; var sum, n : array [1..maxt] of longint; c, p : array [1..maxt,1..maxn] of node; tot : longint; ans : extended; jiong : node; procedure init; var i : longint; begin readln(n[tot]); for i:=1 to n[tot] do with p[tot,i] do readln(x,y); end; procedure qsort(l,r : longint); var i,j : longint; tmp, t : node; function smaller(a,b:node):boolean; begin if (a.y<b.y) or ((a.y=b.y) and (a.x<b.x)) then smaller:=true else smaller:=false; end; begin i:=l; j:=r; t:=p[tot,random(r-l)+1+l]; repeat while (i<=j) and smaller(p[tot,i],t) do inc(i); while (i<=j) and smaller(t,p[tot,j]) do dec(j); if i<=j then begin tmp:=p[tot,i]; p[tot,i]:=p[tot,j]; p[tot,j]:=tmp; inc(i); dec(j); end; until i>j; if l<j then qsort(l,j); if i<r then qsort(i,r); end; function dbl(p0,p1,p2:node):longint; // 叉积 .... begin dbl:=(p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); end; procedure convex; var t, i, m: longint; procedure add(size,k:longint); // 叉积为 负 入栈 ...否则弹出.... begin while (m>=size+2) and (dbl(c[tot,m-1],c[tot,m],p[tot,k])>=0) do dec(m); inc(m); c[tot,m]:=p[tot,k]; end; begin c[tot,1]:=p[tot,1]; c[tot,2]:=p[tot,2]; m:=2; // 逆时针... for i:=3 to n[tot] do add(0,i); // 先到顶 ... t:=m-1; for i:=n[tot]-1 downto 1 do add(t,i); // 再下来.... dec(m); n[tot]:=m; end; procedure area; // 求凸包面积... 两两相邻的叉积和...... var i: longint; z : node; begin z.x:=0; z.y:=0; sum[tot]:=0; for i:=1 to n[tot] do sum[tot]:=sum[tot]+dbl(z,c[tot,i],c[tot,i+1]); sum[tot]:=abs(sum[tot]); end; procedure out ; var i : longint; begin assign(output,ouf);rewrite(output); { for i:=1 to tot do writeln(sum[I]/2:0:2);} writeln(ans/2:0:2); close(output); end; procedure work; var i : longint; function inside(k : longint):boolean; // 判断 点是否在凸包内... 向左引1条射线... 交了奇数根线段则在内...否则再外... var t, q, a, b, ct : longint; tmp : longint; begin ct:=0; for q:=1 to n[k] do begin t:=dbl(jiong,c[k,q],c[k,q+1]); // 算叉积... if t=0 then begin // 等于零 则在凸包边上... inside:=false; exit; end; a:=c[k,q].y; b:=c[k,q+1].y; if a<b then begin //保证是 上面的点到下面的点...(y轴)... tmp:=a; a:=b; b:=tmp; t:=-t; end; if (a>jiong.y) and (jiong.y>=b) and (t>0) then inc(ct); // 此线段跨过这点...且是右手旋转... end; inside:=odd(ct); end; begin for i:=1 to tot do if inside(i) then ans:=ans+sum[I]; end; begin randomize; assign(input,inf);reset(input); repeat inc(tot); init; // 输入段 if n[tot]=-1 then break; qsort(1,n[tot]); // 构建凸包之前要快排的吧...按Y从小到大..若相同则按X 从小到大.... convex; // 构建凸包....逆时针顺序.... area; // 求面积.... 就是以1个点为P0计算叉积....取个绝对值就OK 了 until false; dec(tot); readln(jiong.x,jiong.y); close(input); work; out; end. |

浙公网安备 33010602011771号