裂开(
查看原帖
裂开(
538609
Neutralized楼主2022/2/15 10:20

应该是精度问题
WA了大概15次
全都在第一个点
但是我调不出来
球球大佬帮帮我
今天之内给关注

#include <iostream>
#include <cmath>
#include <algorithm>
#include <bitset>
#include <iomanip>
#include <vector>
#define db double
#define MAXN 50001
using namespace std;
#define ri register int

inline void syncwithme(){
    ios::sync_with_stdio(false);
    cin.tie(NULL),cout.tie(NULL);
}

#define eps 1e-7
inline db chk(db x){ return fabs(x)<eps?0:x; }

struct victor{
    db x,y;
    victor() { }
    victor(db x,db y) : x(chk(x)),y(chk(y)){ }
    inline victor operator +(const victor &a){ return victor(x+a.x,y+a.y); } //加
    inline victor operator -(const victor &a){ return victor(x-a.x,y-a.y); } //减
    inline db operator *(const victor &a){ return x*a.x+y*a.y; } //点积
    inline db operator ^(const victor &a){ return x*a.y-y*a.x; } //叉积的值
    inline void operator +=(const victor &a){ x+=a.x,y+=a.y; }
    inline void operator -=(const victor &a){ x-=a.x,y-=a.y; }
    inline bool operator ==(const victor &a){ return x==a.x&&y==a.y; } //判断两个向量相等
    inline bool iszero(){ return (!x)&&(!y); } //判断是否是零向量
    inline db sqr(){ return x*x+y*y; }
};
inline bool cmp(victor a,victor b){ return a.x!=b.x?a.x<b.x:a.y<b.y; }
victor pt[MAXN];
int n,sta[MAXN<<1],top;
bitset<MAXN> vis;
inline void Andrew(){
    sort(pt+1,pt+n+1,cmp);
    sta[++top]=1;
    for(ri i=2;i<=n;i++){
        while((top^1)&&((pt[sta[top-1]]-pt[sta[top]])^(pt[i]-pt[sta[top]]))>=0)
        vis[sta[top--]]=0;
        vis[i]=1,sta[++top]=i;
    } ri t=top;
    for(ri i=n-1;i>=1;i--){
    	if(vis[i]) continue;
        while((top^t)&&((pt[sta[top-1]]-pt[sta[top]])^(pt[i]-pt[sta[top]]))>=0)
        vis[sta[top--]]=0;
        vis[i]=1,sta[++top]=i;
    }
}
#define S(a,b,c) chk(abs((pt[a]-pt[b])^(pt[c]-pt[b])))
#define L(a,b,c) chk((pt[a]-pt[b])*(pt[c]-pt[b]))
int st; db ans=1e10;
victor p[4];
inline void Spinning(){
    register db t1,t2,t3;
    ri p1(3),p2(2),p3(2); //p1:上方 p2:左边 p3:右边
    for(ri i=1;i<=top-1;i++){
        while(S(sta[i],sta[i+1],sta[p1])<=S(sta[i],sta[i+1],sta[p1%top+1]))
        p1=p1%top+1;
		while(L(sta[i],sta[i+1],sta[p3])>=L(sta[i],sta[i+1],sta[p3%top+1]))
        p3=p3%top+1;
        if(i==1) p2=p3;
        while(L(sta[i],sta[i+1],sta[p2])<=L(sta[i],sta[i+1],sta[p2%top+1]))
        p2=p2%top+1;
        //printf("p1=%d p2=%d p3=%d On Line %d\n",p1,p2,p3,i);
        t1=S(sta[i],sta[i+1],sta[p1]),
        t2=L(sta[i],sta[i+1],sta[p2])+L(sta[i+1],sta[i],sta[p3]),
        t3=L(sta[i],sta[i+1],sta[i]); t2-=t3;
        if(ans>chk(t1*t2/t3)){
            ans=chk(t1*t2/t3);
            /*
	            3
				0 1
				0 1.00001
				20000 0
			*/
            register db k1,b1,k2,b2,x,y;
            if(pt[sta[i+1]].x==pt[sta[i]].x){
            	p[0]=victor(pt[sta[i]].x,pt[sta[i]].y);
            	p[1]=victor(pt[sta[i]].x,pt[sta[i+1]].y);
            	p[2]=victor(pt[sta[p3]].x,pt[sta[i+1]].y);
            	p[3]=victor(pt[sta[p3]].x,pt[sta[i]].y);
			} else if(pt[sta[i+1]].y==pt[sta[i]].y){
				p[0]=victor(pt[sta[i]].x,pt[sta[i]].y);
				p[1]=victor(pt[sta[i+1]].x,pt[sta[i]].y);
				p[2]=victor(pt[sta[i+1]].x,pt[sta[p3]].y);
				p[3]=victor(pt[sta[i]].x,pt[sta[p3]].y);
			} else{
				k1=chk(chk((pt[sta[i+1]].y-pt[sta[i]].y))/chk((pt[sta[i+1]].x-pt[sta[i]].x)));
	            b1=chk(pt[sta[i]].y-k1*pt[sta[i]].x);
	           	// printf("k1 = %.5lf , b1 = %.5lf\n",k1,b1);
	            //当前旋转的底边的斜率和截距
	            k2=chk(-1.0/k1);
            	b2=chk(pt[sta[p2]].y-k2*pt[sta[p2]].x);
				// printf("k2 = %.5lf , b2 = %.5lf\n",k2,b2);
	            //垂直于底边的左直线
	            p[0]=victor((b2-b1)/(k1-k2),(k1*b2-k2*b1)/(k1-k2)); //左下的顶点
	            b2=chk(pt[sta[p3]].y-k2*pt[sta[p3]].x);; //最右边垂直边的截距
	            p[1]=victor((b2-b1)/(k1-k2),(k1*b2-k2*b1)/(k1-k2)); //右下的顶点
	            b1=chk(pt[sta[p1]].y-k1*pt[sta[p1]].x); //最上面平行边的截距
	            p[2]=victor((b2-b1)/(k1-k2),(k1*b2-k2*b1)/(k1-k2)); //右上的顶点
	            b2=chk(pt[sta[p2]].y-k2*pt[sta[p2]].x);
	            p[3]=victor((b2-b1)/(k1-k2),(k1*b2-k2*b1)/(k1-k2)); //左上的顶点	
			}
        }
    }
}

int main()
{
    syncwithme();
    cin>>n; db x,y;
    for(ri i=1;i<=n;i++)
    cin>>x>>y,pt[i]=victor(x,y);
    Andrew();
    Spinning();
    for(ri i=0;i<=3;i++)
    if(p[i].y<p[st].y||(p[i].y==p[st].y&&p[i].x<p[st].x)) st=i;
    cout<<fixed<<setprecision(5)<<ans<<endl;
    //cout<<"st="<<st<<endl;
    for(ri i=0;i<=3;i++)
    cout<<p[(st+i)%4].x<<" "<<p[(st+i)%4].y<<endl;
    return 0;
}

计算几何真好玩
这两天一道题都不卡

我回去打主席树了

2022/2/15 10:20
加载中...