1. 程式人生 > >bzoj 1670 Building the Moat護城河的挖掘 —— 凸包

bzoj 1670 Building the Moat護城河的挖掘 —— 凸包

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=1670

單調棧維護凸包即可,用叉積判斷;

維護上凸殼,然後把所有點的縱座標翻轉再求上凸殼即可,要注意排序規則略有變化。

程式碼如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double db;
int const xn=5005;
db const eps=1e-8;
int n,top,mx;
db ans;
struct N{ db x,y; N(db x=0,db y=0):x(x),y(y) {} bool operator < (const N &b) const {return x<b.x||(x==b.x&&y<b.y);} }p[xn],sta[xn]; bool cmp(N a,N b){return a.x<b.x||(a.x==b.x&&a.y>b.y);} N operator - (const N &a,const N &b){return N(a.x-b.x,a.y-b.y);}
int rd() { int ret=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return f?ret:-ret; } int maxx(int x,int y){return x<y?y:x;} db sqr(db x){return x*x;} db cross(N a,N b){return a.x*b.y-a.y*b.x;} db len(N a){
return sqrt(sqr(a.x)+sqr(a.y));} db dis(N a,N b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));} int dmp(db x){if(fabs(x)<=eps)return 0; return x>eps?1:-1;} void work() { top=0; for(int i=1;i<=n;i++) { while(top>1&&dmp(cross(sta[top]-sta[top-1],p[i]-sta[top]))>=0)top--; sta[++top]=p[i]; } while(top>1)ans+=len(sta[top]-sta[top-1]),top--; } int main() { n=rd(); mx=0; for(int i=1;i<=n;i++)p[i].x=rd(),p[i].y=rd(),mx=maxx(mx,p[i].y); sort(p+1,p+n+1); work(); for(int i=1;i<=n;i++)p[i].y=mx-p[i].y+1; sort(p+1,p+n+1,cmp);// work(); printf("%.2f\n",ans); return 0; }