• 洛谷P2742 Fencing the Cows


    传送门

    题解

    二维凸包模板题。
    使用简单迅速的 Graham Scan 算法可以直接求出整个凸包。算法流程:

    • 选出所有点中 y 坐标最小的点,作为原点,建立极坐标系。
    • 将其余点以极角排序,极角相同看长度
    • 将基准点与第一点入栈,依次扫描之后的点,设栈顶点为 (b),栈顶之下一个点为 (a),当前扫描到的点是 (c),如果 (vec{ab}) 转向 (vec{ac}) 为顺时针,那么将 (b) pop出栈。判断位置使用向量叉积实现,如果顺时针,那么 (vec{ab} imesvec{ac}<0)
    • 扫描完所有点之后,栈里面的所有点构成凸包。

    代码

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    #define xx first
    #define yy second
    using namespace std;
    typedef long long LL;
    typedef pair<double,double> PDD;
    const int N=3e5+10;
    const double PI=acos(-1.0);
    int n,top;
    PDD p[N],sta[N];
    double ans;
    double X(PDD a,PDD b,PDD c){
    	return (b.xx-a.xx)*(c.yy-a.yy)-(c.xx-a.xx)*(b.yy-a.yy);
    }
    double len(PDD a,PDD b){
    	return sqrt((a.xx-b.xx)*(a.xx-b.xx)+(a.yy-b.yy)*(a.yy-b.yy)); 
    }
    bool cmp(PDD a,PDD b){
    	double pp=X(p[1],a,b);
    	if(pp>0) return true;
    	if(pp<0) return false;
    	return len(p[1],a)<len(p[1],b);
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].xx,&p[i].yy);
    	if(n==1) return printf("0.00
    "),0;
    	else if(n==2) return printf("%.2lf
    ",len(p[1],p[2])),0;
    	for(int i=1;i<=n;i++)
    		if(p[i].yy<p[1].yy||p[i].yy==p[1].yy&&p[i].xx<p[1].xx)
    			swap(p[i],p[1]);
    	sort(p+2,p+n+1,cmp);
    	sta[++top]=p[1];sta[++top]=p[2];
    	for(int i=3;i<=n;i++){
    		while(top>1&&X(sta[top-1],sta[top],p[i])<=0) top--;
    		sta[++top]=p[i];
    	}
    	for(int i=1;i<top;i++) ans+=len(sta[i],sta[i+1]);
    	ans+=len(sta[top],p[1]);
    	printf("%.2lf
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    php 解析xml
    php
    php 设置自动加载某个页面
    Mac
    mysql
    Git
    C#
    C# 正则表达式
    C# ASCII码排序
    (转)datagridview 自定义列三步走
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/12562900.html
Copyright © 2020-2023  润新知