热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

UVa11978福岛核爆问题:圆与多边形的交集面积计算及二分法应用

题目《UVa11978福岛核爆问题》涉及圆与多边形交集面积的计算及二分法的应用。该问题的核心在于通过精确的几何运算与高效的算法实现来解决复杂图形的面积计算。在实现过程中,特别需要注意的是对多边形顶点的平移处理,确保所有顶点包括最后一个顶点\(p[n]\)都经过正确的位移,以避免因细节疏忽导致的错误。此外,使用循环次数为50次的二分法能够有效提高算法的精度和稳定性。

题目地址:pdf版本

和上一个题目几乎是一模一样的,就不说思路了。

但是呢,这次是用for 50次写的二分,然后,容易wa的一点是,要把p[n] 也进行平移,漏掉了就wa了啊

代码:

#include
#include
#include
#include
#include
const  long double eps=1e-10;
const long double PI=acos(-1.0);

using namespace std;


struct Point{
    long double x;
    long double y;
    Point(long double x=0,long double y=0):x(x),y(y){}
    void operator<<(Point &A) {cout<eps)-(x<-eps); }
int sgn(long double x)  {return (x>eps)-(x<-eps); }
typedef  Point  Vector;

Vector  operator +(Vector A,Vector B) { return Vector(A.x+B.x,A.y+B.y);}

Vector  operator -(Vector A,Vector B) { return Vector(A.x-B.x,A.y-B.y); }

Vector  operator *(Vector A,long double p) { return Vector(A.x*p,A.y*p);  }

Vector  operator /(Vector A,long double p) {return Vector(A.x/p,A.y/p);}



ostream &operator<<(ostream & out,Point & P) { out<0)    return Length(v3);
    
    else return DistanceToLine(P, A, B);
    
}

Point GetLineProjection(Point P,Point A,Point B)
{
    Vector v=B-A;
    Vector v1=P-A;
    long double t=Dot(v,v1)/Dot(v,v);
    
    return  A+v*t;
}

bool  SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
{
    long double c1=Cross(b1-a1, a2-a1);
    long double c2=Cross(b2-a1, a2-a1);
    long double c3=Cross(a1-b1, b2-b1);
    long double c4=Cross(a2-b1, b2-b1);
    
    return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0 ;
    
}

bool  OnSegment(Point P,Point A,Point B)
{
    return dcmp(Cross(P-A, P-B))==0&&dcmp(Dot(P-A,P-B))<=0;
}

long double PolygonArea(Point *p,int n)
{
    long double area=0;
    
    for(int i=1;i &sol)
{
    long double a=L.v.x;
    long double b=L.p.x-C.c.x;
    long double c=L.v.y;
    long double d=L.p.y-C.c.y;
    
    long double e=a*a+c*c;
    long double f=2*(a*b+c*d);
    long double g=b*b+d*d-C.r*C.r;
    
    long double delta=f*f-4*e*g;
    
    if(dcmp(delta)<0) return 0;
    
    if(dcmp(delta)==0)
    {
        t1=t2=-f/(2*e);
        sol.push_back(L.point(t1));
        return 1;
    }
    
    else
    {
        t1=(-f-sqrt(delta))/(2*e);
        t2=(-f+sqrt(delta))/(2*e);
        
        sol.push_back(L.point(t1));
        sol.push_back(L.point(t2));
        
        return 2;
    }
    
}

// 向量极角公式

long double angle(Vector v)  {return atan2(v.y,v.x);}

int getCircleCircleIntersection(Circle C1,Circle C2,vector &sol)
{
    long double d=Length(C1.c-C2.c);
    
    if(dcmp(d)==0)
    {
        if(dcmp(C1.r-C2.r)==0)  return -1;  // 重合
        else return 0;    //  内含  0 个公共点
    }
    
    if(dcmp(C1.r+C2.r-d)<0)  return 0;  // 外离
    if(dcmp(fabs(C1.r-C2.r)-d)>0)  return 0;  // 内含
    
    long double a=angle(C2.c-C1.c);
    long double da=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));
    
    Point p1=C1.point(a-da);
    Point p2=C1.point(a+da);
    
    sol.push_back(p1);
    
    if(p1==p2)  return 1; // 相切
    else
    {
        sol.push_back(p2);
        return 2;
    }
}


//  求点到圆的切线

int getTangents(Point p,Circle C,Vector *v)
{
    Vector u=C.c-p;
    
    long double dist=Length(u);
    
    if(dcmp(dist-C.r)<0)  return 0;
    
    else if(dcmp(dist-C.r)==0)
    {
        v[0]=Rotate(u,PI/2);
        return 1;
    }
    
    else
    {
        
        long double ang=asin(C.r/dist);
        v[0]=Rotate(u,-ang);
        v[1]=Rotate(u,+ang);
        return 2;
    }
    
}

//  求两圆公切线


int getTangents(Circle A,Circle B,Point *a,Point *b)
{
    int cnt=0;
    
    if(A.r0)   // 外离   又有两条外公切线
    {
        long double  ang_in=acos(rsum/d);
        a[cnt]=A.point(base+ang_in);
        b[cnt]=B.point(base+ang_in+PI);
        cnt++;
        a[cnt]=A.point(base-ang_in);
        b[cnt]=B.point(base-ang_in+PI);
        cnt++;
    }
    
    return cnt;
}



Point Zero=Point(0,0);

long double  common_area(Circle C,Point A,Point B)
{
   // if(A==B)  return 0;
    if(A==C.c||B==C.c)  return 0;

    long double  OA=Length(A-C.c),OB=Length(B-C.c);
    long double  d=DistanceToLine(Zero, A, B);

    int sg=sgn(Cross(A,B));
    if(sg==0)  return 0;

    long double angle=Angle(A,B);

    if(dcmp(OA-C.r)<=0&&dcmp(OB-C.r)<=0)
    {
        return Cross(A,B)/2;

    }

    else if(dcmp(OA-C.r)>=0&&dcmp(OB-C.r)>=0&&dcmp(d-C.r)>=0)
    {
        return  sg*C.r*C.r*angle/2;

    }
    else if (dcmp(OA-C.r)>=0&&dcmp(OB-C.r)>=0&&dcmp(d-C.r)<0)
    {


        Point prj=GetLineProjection(Zero, A, B);

        if(OnSegment(prj, A, B))
        {
        vector p;
        Line L=Line(A,B-A);
        long double t1,t2;
        getLineCircleIntersection(L,C, t1, t2, p);

        long double s1=0;
        s1=C.r*C.r*angle/2;

        long double s2=0;
        s2=C.r*C.r*Angle(p[0],p[1])/2;
        s2-=fabs(Cross(p[0],p[1])/2);
        s1=s1-s2;

        return  sg*s1;
        }

        else
        {
            return sg*C.r*C.r*angle/2;
        }

    }
    else
    {
       
            if(dcmp(OB-C.r)<0)
            {
               
                Point temp=A;
                A=B;
                B=temp;
            }

         Point inter_point;
        
            long double t1,t2;
            Line L=Line(A,B-A);
            vector inter;
            getLineCircleIntersection(L, C, t1, t2,inter);
        
                    if(OnSegment(inter[0], A, B))
                inter_point=inter[0];
            else
            {
                inter_point=inter[1];

            }

        
//        两种方法求交点都可以
//        Point  prj=GetLineProjection(Zero, A, B);
//        
//        Vector v=B-A;
//        v=v/Length(v);
//        long long double mov=sqrt(C.r*C.r-d*d);
//        
//        if(OnSegment(prj+v*mov, A, B))
//        {
//            inter_point=prj+v*mov;
//        }
//        else
//        {
//            inter_point=prj+Vector(-v.x,-v.y)*mov;
//        }
        
        
            long double s=fabs(Cross(inter_point, A)/2);
            s+=C.r*C.r*Angle(inter_point,B)/2;

            return s*sg;


    }
}

Point p[5500];

int main()
{
    int n;
    Circle C;
    int index=0;
    int T;
    cin>>T;
    long  double  P;
    while(cin>>n)
    {
        for(int i=0;i>P;
        
        
        for(int i=0;i<=n;i++)   // wa!
            p[i]=p[i]-C.c;
        
    
        
        
        C.c=Zero;
        
       
    
        long double l=0,r=1e4;
        long double mid=l;
        
        for(int tim=0;tim<50;tim++)
        {
            mid=l+(r-l)/2;
            
            C.r=mid;
            
            long double ans=0;
        
           for(int i=0;i=area*P/100.0)  r=mid;
            else l=mid;
        }
        
       // if(mid-floor(mid)>0.5) mid+=1;
        printf("Case %d: %.0Lf\n",++index,mid);
        
        
    }

}



推荐阅读
  • 深入解析零拷贝技术(Zerocopy)及其应用优势
    零拷贝技术(Zero-copy)是Netty框架中的一个关键特性,其核心在于减少数据在操作系统内核与用户空间之间的传输次数。通过避免不必要的内存复制操作,零拷贝显著提高了数据传输的效率和性能。本文将深入探讨零拷贝的工作原理及其在实际应用中的优势,包括降低CPU负载、减少内存带宽消耗以及提高系统吞吐量等方面。 ... [详细]
  • POJ 1696: 空间蚂蚁算法优化与分析
    针对 POJ 1696 的空间蚂蚁算法进行了深入的优化与分析。本研究通过改进算法的时间复杂度和空间复杂度,显著提升了算法的效率。实验结果表明,优化后的算法在处理大规模数据时表现优异,能够有效减少计算时间和内存消耗。此外,我们还对算法的收敛性和稳定性进行了详细探讨,为实际应用提供了可靠的理论支持。 ... [详细]
  • 在幼儿园中,有 \( n \) 个小朋友需要通过投票来决定是否午睡。尽管这个问题对每个孩子来说并不是特别重要,但他们仍然希望通过谦让的方式达成一致。每个人都有自己的偏好,但为了集体和谐,他们决定采用一种最小割的方法来解决这一问题。这种方法不仅能够确保每个人的意愿得到尽可能多的尊重,还能找到一个最优的解决方案,使整体满意度最大化。 ... [详细]
  • 题目旨在解决树上的路径最优化问题,具体为在给定的树中寻找一条长度介于L到R之间的路径,使该路径上的边权平均值最大化。通过点分治策略,可以有效地处理此类问题。若无长度限制,可采用01分数规划模型,将所有边权减去一个常数m,从而简化计算过程。此外,利用单调队列优化动态规划过程,进一步提高算法效率。 ... [详细]
  • 2017广西邀请赛复盘:NWAFU全国邀请赛训练赛第八场
    本次训练赛(NWAFU全国邀请赛复盘之一)基于2017年广西邀请赛的赛题,重点解析了A、E、F、G等关键题目,旨在通过复盘帮助参赛者深入理解相关知识点和技术应用,为后续比赛提供宝贵经验。 ... [详细]
  • 考研数据结构复习:链式栈深入解析与应用
    在考研数据结构复习中,链式栈的深入解析与应用是一个重要环节。本文详细探讨了链式栈的实现方法,特别是栈底和栈顶指针的使用。通过对比常见的单链表实现方式,本文整理了一份代码示例,与王道复习指导中的链式存储类型高度一致。此外,本文还提供了详细的注释和解释,帮助读者更好地理解和掌握链式栈的原理与应用。 ... [详细]
  • 在2015年世界总决赛的Tours问题中,参赛者面临一个包含n个节点和m条边的无向图挑战。任务是选定一种颜色数量k,并使用这些颜色为每条边着色。核心要求是在图中的任何简单循环中,每种颜色的边数必须相等。该研究对竞赛路线进行了全面分析,探讨了满足条件的所有可能的着色方案。 ... [详细]
  • Candyland的糖果公园以其独特的结构吸引了众多喜爱糖果的小朋友。公园内设有多个游览点,每个点不仅景色宜人,还提供免费的糖果。这些游览点通过复杂的路径连接,形成了一棵包含n个节点的树状结构。为了优化游客体验,公园管理团队采用了一种基于树上动态修改的莫队算法,有效提升了糖果发放和游玩项目的管理效率。 ... [详细]
  • 本文详细介绍了如何使用C++实现邻接表数据结构。邻接表是一种用于表示图的数据结构,特别适用于稀疏图的存储。通过定义最大顶点数和顶点类型,本文展示了如何利用标准模板库(STL)中的容器来构建和操作邻接表,从而高效地管理和查询图中的节点及其连接关系。此外,还提供了具体的代码示例,帮助读者更好地理解和应用这一数据结构。 ... [详细]
  • Codeforces 1065D 解题心得与代码实现分析 ... [详细]
  • 深入解析 iOS Objective-C 中的对象内存对齐规则及其优化策略
    深入解析 iOS Objective-C 中的对象内存对齐规则及其优化策略 ... [详细]
  • 掌握DSP必备的56个核心问题,我已经将其收藏以备不时之需! ... [详细]
  • 在解决这道题时,我们继续使用AC自动机结合矩阵乘法优化动态规划的方法。与前一题类似,采用了补集转化的思想。不过,本题需要额外构建一个小矩阵来计算 \(26^1 + 26^2 + \ldots + 26^L\) 的值,并且还需要求解所有状态的总和 \(f\),以应对不同长度的字符串情况。这种方法不仅提高了算法效率,还确保了对各种输入规模的良好适应性。 ... [详细]
  • 本研究基于状态空间方法,通过动态可视化技术实现了汉诺塔问题的求解过程,即将n个盘子从A柱移动到C柱。本文提供了一个使用C语言在控制台进行动画绘制的示例,并详细注释了程序逻辑,以帮助读者更好地理解和学习该算法。 ... [详细]
  • 在MFC开发过程中,利用Windows内置的文件对话框可以显著提高文件操作的效率。本文总结了使用文件对话框进行文件选择和处理的经验,详细介绍了相关API的调用方法和参数设置,如`CFileDialog`类的使用、结构体`OPENFILENAME`的配置以及如何获取选中的文件路径。通过这些技巧,开发者可以快速实现文件的打开、保存等功能,提升应用程序的用户体验。 ... [详细]
author-avatar
mobiledu2502927397
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有