ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

洛谷-P3829-[SHOI2012]信用卡凸包(凸包,注意精度!!!!!!)

2019-03-10 11:53:41  阅读:352  来源: 互联网

标签:Dots Ang 洛谷 Top 凸包 Stk Ang1 include SHOI2012


题目链接:https://www.luogu.org/problemnew/show/P3829

题目大意:中文题,易理解。

思路:Fuck!!精度卡了我一页的WA...(还是太菜了)经过简单的草图,如下图所示:随便举一个例子,然后发现,周长就是里面的小的多边形的周长+圆的周长。至于具体的证明,这不是显而易见的么??然后就是求出每个矩形的四个点,然后求出凸包,就行了,简单的板子题,半个小时搞定!

好了好了!!板子确实好写,主要是精度!!四个点的坐标。。一开始我用的:

            Ang1=atan2(b,a);Dots[++Ecnt]=Point(x+C*cos(Ang+Ang1),y+C*sin(Ang+Ang1));
            Ang1=atan2(b,-a);Dots[++Ecnt]=Point(x+C*cos(Ang+Ang1),y+C*sin(Ang+Ang1));
            Ang1=atan2(-b,a);Dots[++Ecnt]=Point(x+C*cos(Ang+Ang1),y+C*sin(Ang+Ang1));
            Ang1=atan2(-b,-a);Dots[++Ecnt]=Point(x+C*cos(Ang+Ang1),y+C*sin(Ang+Ang1));

结果WA了5,6,10三个测试点。我还以为是我板子的问题,调了一节课(毛概一整节课都没调出来啊)。回寝室之后继续调,结果还是没有跳出来,我又写了一个Jaris法,还是5,6,10测试点。。这时我还以为是板子的问题(呜呜呜。。。

结果早上试着用其他方法得到四个点,发现就过了。。。万恶的精度啊!!不过也是,三角函数用了个遍,精度肯定损失到爆炸...

ACCode:


// luogu-judger-enable-o2
//#pragma comment(linker, "/STACK:1024000000,1024000000")
 
#include<stdio.h>
#include<string.h>
#include<math.h>
 
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
 
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e4+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);

struct Point{
    double x,y;
    Point(double _x=0,double _y=0){
        x=_x;y=_y;
    }
    friend Point operator + (const Point &a,const Point &b){
        return Point(a.x+b.x,a.y+b.y);
    }
    friend Point operator - (const Point &a,const Point &b){
        return Point (a.x-b.x,a.y-b.y);
    }
    friend double operator ^ (const Point &a,const Point &b){
        return a.x*b.y-a.y*b.x;
    }
    friend bool operator == (const Point &a,const Point &b){
        return fabs(a.x-b.x)<EPS&&fabs(a.y-b.y)<EPS;
    }
};
struct V{
    Point start,end;
    V(Point _start=Point(0,0),Point _end=Point(0,0)){
        start=_start;end=_end;
    }
};
Point Dots[MAXN<<2];
Point Stk[MAXN<<2];int Top;
double A,B,R;
int N,Ecnt;

double Distance(Point a,Point b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double Prellel(double key){
    return fabs(key)<EPS?0:key;
}
int Cmp(Point a,Point b){
    double res=Prellel((a-Dots[1])^(b-Dots[1]));
    if(res>0) return 1;
    if(res==0&&Distance(a,Dots[1])<Distance(b,Dots[1])) return 1;
    return 0;
}
int Cmp2(Point a,Point b){
	return (a.y<b.y||(a.y==b.y&&a.x<b.x));
}
int Judge(int k,int i){
    if(Dots[i].y<Dots[k].y||(Dots[i].y==Dots[k].y&&Dots[i].x<Dots[k].x)) return 1;
    return 0;
}
void Graham(){
	int k=1;
    for(int i=2;i<=Ecnt;++i){
//		cout<<"DOts: "<<Dots[i].x<<" "<<Dots[i].y<<endl;
    	if(Judge(k,i)) k=i;
    }swap(Dots[1],Dots[k]);
    sort(Dots+2,Dots+1+Ecnt,Cmp);
    Top=0;Stk[++Top]=Dots[1];
    for(int i=2;i<=Ecnt;++i){
    	while(Top>=3&&((Dots[i]-Stk[Top-1])^(Stk[Top]-Stk[Top-1]))>=0) --Top;
//        while(Top>=3&&((Stk[Top]-Stk[Top-1])^(Dots[i]-Stk[Top-1]))<EPS) --Top;
        Stk[++Top]=Dots[i];
    }//Stk[Top+1]=Stk[1];
}
void Jarvis(){
	int len;Top=0;
	sort(Dots+1,Dots+1+N,Cmp2);
	Stk[++Top]=Dots[1];Stk[++Top]=Dots[2];
	for(int i=3;i<=N;++i){
		while(Top>=2&&((Dots[i]-Stk[Top-1])^(Stk[Top-1]-Stk[Top]))>=0) --Top;
		Stk[++Top]=Dots[i];
	}int Bot=Top;
	for(int i=N-1;i>0;--i){
		while(Top>Bot&&((Dots[i]-Stk[Top-1])^(Stk[Top-1]-Stk[Top]))>=0) --Top;
		Stk[++Top]=Dots[i];
	}Stk[Top+1]=Stk[1];
}
Point rotate(Point a,double Ang){
    double c=cos(Ang),s=sin(Ang);
    return Point(a.x*c-a.y*s,a.x*s+a.y*c);
}
int main(){
    while(~scanf("%d",&N)){
        scanf("%lf%lf%lf",&A,&B,&R);
//		double a=A/2.0,b=B/2.0,r=R;
//        double a=A/2.0-R,b=B/2.0-R;
		double a=A-R*2.0,b=B-R*2.0;
//		cout<<a<<" "<<b<<endl;
        double C=sqrt(a*a+b*b);
        double x,y,Ang;Ecnt=0;
        double Ang1;
//		cout<<"C is : "<<C<<endl;
        for(int i=1;i<=N;++i){
            scanf("%lf%lf%lf",&x,&y,&Ang);
            
            Point k(x,y),d,v;double rad=Ang;
			d=Point(x+b/2,y-a/2),v=rotate(k-d,rad),Dots[++Ecnt]=k+v;
			d=Point(x-b/2,y-a/2),v=rotate(k-d,rad),Dots[++Ecnt]=k+v;
			d=Point(x+b/2,y+a/2),v=rotate(k-d,rad),Dots[++Ecnt]=k+v;
			d=Point(x-b/2,y+a/2),v=rotate(k-d,rad),Dots[++Ecnt]=k+v;
//			Dots[++Ecnt]=rotate(Point(a-r,b-r),Ang)+Point(x,y);
//			Dots[++Ecnt]=rotate(Point(r-a,b-r),Ang)+Point(x,y);
//			Dots[++Ecnt]=rotate(Point(r-a,r-b),Ang)+Point(x,y);
//			Dots[++Ecnt]=rotate(Point(a-r,r-b),Ang)+Point(x,y);
//            Ang1=atan2(b,a);Dots[++Ecnt]=Point(x+C*cos(Ang+Ang1),y+C*sin(Ang+Ang1));
//            Ang1=atan2(b,-a);Dots[++Ecnt]=Point(x+C*cos(Ang+Ang1),y+C*sin(Ang+Ang1));
//            Ang1=atan2(-b,a);Dots[++Ecnt]=Point(x+C*cos(Ang+Ang1),y+C*sin(Ang+Ang1));
//            Ang1=atan2(-b,-a);Dots[++Ecnt]=Point(x+C*cos(Ang+Ang1),y+C*sin(Ang+Ang1));
        }Graham();//Jarvis();
		double ans=2.0*R*PI;
        for(int i=2;i<=Top;++i){
            ans+=Distance(Stk[i],Stk[i-1]);
//			cout<<"the Stk is : "<<ans<<" "<<Stk[i].x<<" "<<Stk[i].y<<endl;
        }ans+=Distance(Stk[1],Stk[Top]);
		printf("%.2lf\n",ans);
    }
}

/*


*/

 

标签:Dots,Ang,洛谷,Top,凸包,Stk,Ang1,include,SHOI2012
来源: https://blog.csdn.net/qq_40482358/article/details/88375333

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有