洛谷P2333 [SCOI2006]一孔之见

Posted Achen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P2333 [SCOI2006]一孔之见相关的知识,希望对你有一定的参考价值。

传送门

辣鸡题目毁我人生败我前程

50分代码

技术分享图片
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#define pi acos(-1)
#define eps 1e-9
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=107;
typedef long long LL;
typedef double db;
using namespace std;
int n,cnt[N];
db S;

template<typename T>void read(T &x)  {
    char ch=getchar(); x=0; T f=1;
    while(ch!=-&&(ch<0||ch>9)) ch=getchar();
    if(ch==-) f=-1,ch=getchar();
    for(;ch>=0&&ch<=9;ch=getchar()) x=x*10+ch-0; x*=f;
}

struct pt {
    db x,y;
    pt(){}
    pt(db x,db y):x(x),y(y){}
}p[N],jd[N][2];

struct Line {
    pt a,b;
    Line(){}
    Line(pt a,pt b):a(a),b(b){}
}L[N];

int dcmp(db x) { return fabs(x)<=eps?0:(x>0?1:-1);}
bool operator == (const pt&A,const pt&B) { return dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)==0; }
bool operator < (const pt&A,const pt&B) { return dcmp(A.x-B.x)<0||(dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)<0); }
pt operator * (const pt&A,const db&B) { return pt(B*A.x,B*A.y); }
pt operator / (const pt&A,const db&B) { return pt(A.x/B,A.y/B); }
pt operator + (const pt&A,const pt&B) { return pt(A.x+B.x,A.y+B.y); }
pt operator - (const pt&A,const pt&B) { return pt(A.x-B.x,A.y-B.y); }
db cross(pt A,pt B) { return A.x*B.y-A.y*B.x; }
db dot(pt A,pt B) { return A.x*B.x+A.y*B.y; }
db length(pt A) { return dot(A,A); }
db pf(db x) { return x*x; }

int ck(pt A,Line li) {
    return dcmp(sqrt(length(A-li.a))+sqrt(length(A-li.b))-sqrt(length(li.a-li.b)))==0;
}

void get_jd(int id,Line li,db r) {
    cnt[id]=0;
    db a=li.a.x,b=li.a.y,c=li.b.x,d=li.b.y;
    db e=pf(c-a)+pf(d-b),f=2.0*a*(c-a)+2.0*b*(d-b),g=a*a+b*b-r*r;
    db dt=f*f-4*e*g;
    if(dcmp(dt)<0) return;
    if(dcmp(dt)==0) cnt[id]=1;
    else cnt[id]=2;
    db t1=(-f+sqrt(dt))/e/2.0;
    db t2=(-f-sqrt(dt))/e/2.0;        
    jd[id][0]=pt(a+t1*(c-a),b+t1*(d-b)); 
    jd[id][1]=pt(a+t2*(c-a),b+t2*(d-b));
    if(cnt[id]==2) 
        if(!ck(jd[id][1],li)) cnt[id]--;
    if(!ck(jd[id][0],li)) {
        cnt[id]--;
        if(cnt[id]) jd[id][0]=jd[id][1];
    }
}

int ck(db r) {
    db rs=0;
    int jds=0,f=0;
    For(i,1,n) {
        get_jd(i,L[i],r);
        jds+=cnt[i]; 
        if(cnt[i]==2) f=1;
    }
    if(jds==2&&!f) {
        For(i,1,n) {
            int pr=i==1?n:i-1;
            if(cnt[i]==1&&cnt[pr]==1) {
                pt A=jd[i][0],B=jd[pr][0],C=p[i];
                db a=length(B-C),b=length(A-C),c=length(A-B);
                rs=r*r*acos((a+b-c)/(2.0*sqrt(a)*sqrt(b)));
                rs+=fabs(cross(A,C));
                rs+=fabs(cross(B,C));
                break;
            }
        }
        return dcmp(rs-S*2.0)>=0;
    }
    db sum=2.0*pi;
    For(i,1,n) {
        if(cnt[i]==2) {
            pt A=jd[i][0],B=jd[i][1];
            rs+=fabs(cross(A,B));
            db a=length(B),b=length(A),c=length(A-B);
            sum-=acos((a+b-c)/(2.0*sqrt(a)*sqrt(b)));
        }
    } 
    rs+=r*r*sum;
    return dcmp(rs-S*2.0)>=0;
}

int main() {
#ifdef DEBUG
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
#endif
    read(n); scanf("%lf",&S);
    For(i,1,n) 
        scanf("%lf%lf",&p[i].x,&p[i].y);
    p[n+1]=p[1];
    For(i,1,n) L[i]=Line(p[i],p[i+1]);
    db l=0,r=1e20;
    while(fabs(r-l)>eps) {
        db mid=((l+r)/2.0);
        if(ck(mid)) r=mid;
        else l=mid;
    }
    printf("%.2lf\n",l);
    return 0;
}
View Code

 

以上是关于洛谷P2333 [SCOI2006]一孔之见的主要内容,如果未能解决你的问题,请参考以下文章

LibreOJ #2006. 「SCOI2015」小凸玩矩阵

洛谷 P2327 [SCOI2005]扫雷

洛谷 P2327 [SCOI2005]扫雷

洛谷P3275 [SCOI2011]糖果

洛谷P2327 [SCOI2005]扫雷 枚举 搜索

洛谷 P2324 [SCOI2005]骑士精神