zoukankan      html  css  js  c++  java
  • P3829 [SHOI2012]信用卡凸包

    思路

    注意到结果就是每个信用卡边上的四个圆心的凸包周长+一个圆的周长

    然后就好做了

    注意平行时把距离小的排在前面,栈中至少要有1个元素(top>1),凸包中如果存在叉积为0的点也要pop,否则可能会错。

    几个简单的向量的式子

    [a*b=(x_1y_1+ x_2y_2) ]

    [a imes b=(x_1y_2- x_2y_1) ]

    逆时针旋转( heta)

    [x'=xcos heta-ysin heta\ y'=xsin heta+ycos heta ]

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    struct Vec{
        double x,y;
    	Vec(){};
    	Vec(double xx,double yy){
    		x=xx;
    		y=yy;
    	}
    	double mul(Vec b){
    		return x*b.x+y*b.y;
    	}
    	double cross(Vec b){
    		return x*b.y-y*b.x;
    	}
    	Vec rev(double seta){
    		return Vec(x*cos(seta)-y*sin(seta),x*sin(seta)+y*cos(seta));
    	}
    };
    struct Point{
    	double x,y;
    	Point(){};
    	Point(double xx,double yy){
    		x=xx;
    		y=yy;
    	}
    	Point operator + (Point b){
    		return Point(x+b.x,y+b.y);
    	} 
    	Point operator + (Vec b){
    		return Point(x+b.x,y+b.y);
    	} 
    	Vec operator - (Point b){//b-a a->b
    		return Vec(b.x-x,b.y-y);
    	}
    	Point rev(Point b,double seta){//a 绕 b
    		return b+((Point(x,y))-b).rev(seta);
    	}
    	double dist(Point a){
    		return sqrt((x-a.x)*(x-a.x)+(y-a.y)*(y-a.y));
    	}
    };
    struct Stack{
    	int data[400100],topx=0;
    	void push(int x){
    		data[++topx]=x;
    	}
    	void pop(void){
    		topx--;
    	}
    	int top(void){
    		return data[topx];
    	}
    	int Setop(void){
    		return data[topx-1];
    	}
    };
    Point a[400100];
    Stack S;
    bool cmp(Point x,Point y){
        return (x-a[1]).cross(y-a[1])>0||((x-a[1]).cross(y-a[1])==0&&x.dist(a[1])>y.dist(a[1]));
    }
    int n,cnt;
    double ax,bx,rx,ans=0;
    int main(){
    	scanf("%d",&n);
    	scanf("%lf %lf %lf",&ax,&bx,&rx);
    	for(int i=1;i<=n;i++){
    		double x,y,seta;
    		scanf("%lf %lf %lf",&x,&y,&seta);
    		a[++cnt]=Point(x-bx/2+rx,y+ax/2-rx).rev(Point(x,y),seta);
    		a[++cnt]=Point(x-bx/2+rx,y-ax/2+rx).rev(Point(x,y),seta);
    		a[++cnt]=Point(x+bx/2-rx,y+ax/2-rx).rev(Point(x,y),seta);
    		a[++cnt]=Point(x+bx/2-rx,y-ax/2+rx).rev(Point(x,y),seta);
    	}
    	// for(int i=1;i<=cnt;i++)
    	// 	printf("%lf %lf
    ",a[i].x,a[i].y);
    	int pos=1;
    	for(int i=2;i<=cnt;i++)
    		if(a[i].x<a[pos].x||(a[i].x==a[pos].x&&a[i].y<a[pos].y))
    			pos=i;
    	swap(a[1],a[pos]);
    	sort(a+2,a+cnt+1,cmp);
    	S.push(1);
    	S.push(2);
    	for(int i=3;i<=cnt;i++){
    		while(S.topx>0&&(a[S.Setop()]-a[S.top()]).cross(a[S.Setop()]-a[i])<=0){
    			S.pop();
    		}
    		S.push(i);
    	}
    	int tt=S.top();
    	while(S.topx>1){
    		ans+=a[S.top()].dist(a[S.Setop()]);
    		S.pop();
    	}
    	ans+=a[S.top()].dist(a[tt]);
    	ans+=2*acos(-1.0)*rx;
    	printf("%.2lf
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    2015.05.12:json的常用处理方式
    好菜都得花功夫做
    网站从 IIS6 迁移至 IIS7 后的通配符脚本映射权限配置不当可能导致403错误
    ELearning是学习系统而不是教育系统
    空难与软件开发(一)
    “模态”对话框和“后退”按钮
    闭包解析(Fun with closure)
    关于CultureInfo的两个问题
    从来就不可能精通:关于Boxing
    Windows RT 应用程序开发介绍培训的讲义
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10648046.html
Copyright © 2011-2022 走看看