zoukankan      html  css  js  c++  java
  • HDU 1348 Wall ( 凸包周长 )


    **链接:****传送门 **

    题意:给出二维坐标轴上 n 个点,这 n 个点构成了一个城堡,国王想建一堵墙,城墙与城堡之间的距离总不小于一个数 L ,求城墙的最小长度,答案四舍五入

    思路:城墙与城堡直线长度是相等的,当城堡出现拐角时,城墙必然会出现一段圆弧,这些圆弧最终会构成一个半径为 L 的圆,所以答案就是凸包的周长 + 圆的周长

    balabala:

    1. 采用Jarvis步进法来求凸包,Jarvis步进法复杂度为O(nh),h为凸包顶点个数
    2. 采用Graham-Scan来求凸包,Graham - Scan 法复杂度为O(nlogn)

    如有错误请一定指出!


    Graham - Scan法:

    /*************************************************************************
        > File Name: hdu1348t2.cpp
        > Author:    WArobot 
        > Blog:      http://www.cnblogs.com/WArobot/ 
        > Created Time: 2017年05月07日 星期日 20时49分15秒
     ************************************************************************/
    
    #include<bits/stdc++.h>
    using namespace std;
    
    // Graham - Scan 
    // O(nlgn)
    
    #define PI 3.1415926535
    const int maxn = 1010;
    struct point{
    	double x,y;
    };
    
    
    bool cmp(point a,point b){
    	return (a.y<b.y || (a.y==b.y && a.x<b.x));
    }
    bool mult(point sp,point ep,point op){
    	return (sp.x-op.x)*(ep.y-op.y)>=(sp.y-op.y)*(ep.x-op.x);
    }
    point res[maxn];
    int Graham(point pnt[],int n){
    	int i , len , k = 0 , top = 1;
    	sort(pnt,pnt+n,cmp);
    	if(n == 0)	return 0;	res[0] = pnt[0];
    	if(n == 1)	return 1;	res[1] = pnt[1];
    	if(n == 2)	return 2;	res[2] = pnt[2];
    	for(int i=2;i<n;i++){
    		while( top && mult( pnt[i] , res[top] , res[top-1] ))
    			top--;
    		res[++top] = pnt[i];
    	}
    	len = top;	res[++top] = pnt[n-2];
    	for(i=n-3;i>=0;i--){
    		while( top!=len && mult( pnt[i] , res[top] , res[top-1] ))
    			top--;
    		res[++top] = pnt[i];
    	}
    	return top;
    }
    double point_dis(point a,point b){
    	return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
    }
    int main(){
    	int T , n , L , kase = 0;
    	point pi[maxn];
    	scanf("%d",&T);
    	while(T--){
    		if(kase > 0)	printf("
    ");
    		kase++;
    		scanf("%d%d",&n,&L);
    		for(int i=0;i<n;i++)	scanf("%lf%lf",&pi[i].x,&pi[i].y);
    		int t = Graham(pi,n);
    		double ans = 2*PI*L;
    		for(int i=0;i<t;i++){
    			ans += point_dis( res[i] , res[ (i+1)%t ] );
    		}
    		printf("%.lf
    ",ans);
    	}
    	return 0;
    }
    

    Jarvis步进法:

    /*************************************************************************
        > File Name: hdu1348.cpp
        > Author:    WArobot 
        > Blog:      http://www.cnblogs.com/WArobot/ 
        > Created Time: 2017年05月07日 星期日 18时55分57秒
     ************************************************************************/
    
    #include<bits/stdc++.h>
    using namespace std;
    
    #define PI 3.1415926535
    const int maxn = 1010;
    struct point{
    	double x,y;
    }pi[maxn];
    
    bool cmp(point a,point b){
    	return ( a.y<b.y || a.y==b.y && a.x<b.x);
    }
    
    int n,L,ans[maxn],cnt,sta[maxn],tail;
    // 检查是否严格左转,共线不算左转
    bool CrossLeft(point p1,point p2,point p3){	
    	return ((p3.x-p1.x)*(p2.y-p1.y) - (p2.x-p1.x)*(p3.y-p1.y)) < 0;
    }
    void Jarvis(){
    	tail = cnt = 0;	
    	sort(pi,pi+n,cmp);
    	sta[tail++] = 0;	sta[tail++] = 1;
    	for(int i=2;i<n;i++){
    		while(tail>1 && !CrossLeft( pi[ sta[tail-1] ] , pi[ sta[tail-2] ] , pi[i] ))
    			tail--;
    		sta[ tail++ ] = i;
    	}
    	for(int i=0;i<tail;i++)	ans[cnt++] = sta[i];
    	tail = 0;	sta[ tail++ ] = n-1;	sta[ tail++ ] = n-2;
    	for(int i=n-3;i>=0;i--){
    		while(tail>1 && !CrossLeft( pi[ sta[tail-1] ] , pi[ sta[tail-2] ] , pi[i] ))
    			tail--;
    		sta[ tail++ ] = i;
    	}
    	for(int i=0;i<tail;i++)	ans[cnt++] = sta[i];
    }
    double Point_dis(point a,point b){
    	return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
    }
    int main(){
    	int T , kase = 0;
    	scanf("%d",&T);
    	while(T--){
    		if(kase)	printf("
    ");
    		kase++;
    		scanf("%d%d",&n,&L);
    		for(int i=0;i<n;i++)	scanf("%lf%lf",&pi[i].x,&pi[i].y);
    		Jarvis();
    		double re = 2*PI*L;
    		for(int i=0;i<cnt-1;i++){
    			re += Point_dis( pi[ans[i]] , pi[ans[i+1]] );
    		}
    		printf("%.0lf
    ",re);
    	}
    	return 0; 
    }
  • 相关阅读:
    前端使用 node-gyp 构建 Native Addon
    CHANGELOG 的实现
    深入 JavaScript 中的对象以及继承原理
    使用electron进行原生应用的打包(2)---主进程与渲染进程之间的通信
    使用electron进行原生应用的打包
    Babel编译
    HTML布局四剑客-Flex,Grid,Table,Float
    关于vtt 与 srt 字幕 的相互转换
    关于websocket
    关于jQuery中nth-child和nth-of-type的详解
  • 原文地址:https://www.cnblogs.com/WArobot/p/6822125.html
Copyright © 2011-2022 走看看