Gym 100499H - cctv - 计算几何

题目大致意思是一个矩形,里面有很多小矩形,小矩形是障碍物,问在四个角上能看到的范围面积。

解题思路:

因为障碍物只有20个所以取出每个三角形靠近观望点的三个点。然后将这些点去重排序。然后这些点将这个90度角分割开。对于每个区间暴力枚举所有边,看那条边和这个角组成的三角形最小保存。最后将这些值相加即可。

基本思路可以概括为将可见范围划分成许多由一个角和对应边组成的三角形来求面积。

#include <bits/stdc++.h>
using namespace std;
#define pi acos(-1)
double ex1[1000],ey1[1000],ex2[1000],ey2[1000];
double jiao[1000];
int vis[1000];
double vmax[1000];
struct EDGE {
    double h;
    int fa;
    double c1,c2;
}edge[1000];
int main()
{
    //freopen("test.in","r",stdin);
    double pp=180.0/pi;
    double ans1,ans2,ans3,ans4;
    int t;
    double x1,x2,y1,y2;
    int en,em;
    int n,m,nn;
    int p;
    int sa;
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d%d",&en,&em,&p);
        for(int i=1;i<=p;i++)
            scanf("%lf%lf%lf%lf",&ex1[i],&ey1[i],&ex2[i],&ey2[i]);
        n=en;m=em;

<span style="white-space:pre">	</span>/**这里是以左下角为例求面积**/
        sa=1;                                                                       // 判断是否直接由矩形覆盖观望点。
        for(int i=1;i<=p;i++) {
            x1=ex1[i];x2=ex2[i];y1=ey1[i];y2=ey2[i];<span style="white-space:pre">				</span>  //  建边和建角
            if(x1==0&&y1==0) {
                sa=0;
                break;
            }
            edge[i*2-1].h=x1;
            edge[i*2-1].fa=1;
            edge[i*2].h=y1;
            edge[i*2].fa=0;
            if(x1!=0) edge[i*2-1].c1=atan(y1/x1)*pp; else edge[i*2-1].c1=90.0;
            if(x1!=0) edge[i*2-1].c2=atan(y2/x1)*pp; else edge[i*2-1].c2=90.0;
            if(x2!=0) edge[i*2].c1=atan(y1/x2)*pp; else edge[i*2].c1=90.0;
            if(x1!=0) edge[i*2].c2=atan(y1/x1)*pp; else edge[i*2].c2=90.0;
            jiao[i*3-2]=edge[i*2-1].c1;
            jiao[i*3-1]=edge[i*2-1].c2;
            jiao[i*3]=edge[i*2].c1;
        }
        jiao[p*3+1]=0.0;<span style="white-space:pre">					</span>//将边界的边和0度,45度,90度加入
        jiao[p*3+2]=90;
        jiao[p*3+3]=45.0;
        nn=p*3+3;
        edge[p*2+1].h=n;
        edge[p*2+1].c1=0.0;
        edge[p*2+1].c2=45.0;
        edge[p*2+1].fa=1;
        edge[p*2+2].h=m;
        edge[p*2+2].c1=45.0;
        edge[p*2+2].c2=90.0;
        edge[p*2+2].fa=0;
        sort(jiao+1,jiao+nn+1);
        for(int i=1;i<=nn;i++) {                                  //  去重
            for(int j=i+1;j<=nn;j++) {
                if(fabs(jiao[i]-jiao[j])<1e-9) {
                    for(int k=j;k<nn;k++)
                        jiao[k]=jiao[k+1];
                    j--;
                    nn--;
                }
            }
        }
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=nn;i++) {
            vmax[i]=99999999.0;
        }
        for(int i=1;i<nn;i++) {<span style="white-space:pre">								</span>//暴力枚举求最小面积
            double gg1=jiao[i];
            double gg2=jiao[i+1];
            for(int j=1;j<=p*2+2;j++) {
                if(edge[j].h!=0&&edge[j].c1<=gg1&&edge[j].c2>=gg2) {
                    double ss;
                    if(gg1==0.0) {
                        ss=edge[j].h*tan(gg2/pp)*edge[j].h/2.0;
                    }
                    if(gg2==90.0) {
                        ss=edge[j].h/tan(gg1/pp)*edge[j].h/2.0;
                    }
                    if(gg1!=0.0&&gg2!=90.0) {
                        if(edge[j].fa==0) ss=fabs(edge[j].h/tan(gg2/pp)-edge[j].h/tan(gg1/pp))*edge[j].h/2.0;
                        else ss=fabs(edge[j].h*tan(gg2/pp)-edge[j].h*tan(gg1/pp))*edge[j].h/2.0;
                    }
                    if(ss<vmax[i]) {
                        vmax[i]=ss;
                        vis[i]=j;
                    }
                }
            }
        }
        ans3=0;
        for(int i=1;i<nn;i++) {
            ans3+=vmax[i];
        }
        if(sa==0) ans3=0;

<span style="white-space:pre">	</span>/**以上为以左下角为例之后为重复代码求其他点,只是将输出坐标进行了转换**/

        sa=1;
        for(int i=1;i<=p;i++) {
            x1=ex1[i];x2=ex2[i];y2=m-ey1[i];y1=m-ey2[i];
            if(x1==0&&y1==0) {
                sa=0;
                break;
            }
            edge[i*2-1].h=x1;
            edge[i*2-1].fa=1;
            edge[i*2].h=y1;
            edge[i*2].fa=0;
            if(x1!=0) edge[i*2-1].c1=atan(y1/x1)*pp; else edge[i*2-1].c1=90.0;
            if(x1!=0) edge[i*2-1].c2=atan(y2/x1)*pp; else edge[i*2-1].c2=90.0;
            if(x2!=0) edge[i*2].c1=atan(y1/x2)*pp; else edge[i*2].c1=90.0;
            if(x1!=0) edge[i*2].c2=atan(y1/x1)*pp; else edge[i*2].c2=90.0;
            jiao[i*3-2]=edge[i*2-1].c1;
            jiao[i*3-1]=edge[i*2-1].c2;
            jiao[i*3]=edge[i*2].c1;
        }
        jiao[p*3+1]=0.0;
        jiao[p*3+2]=90;
        jiao[p*3+3]=45.0;
        nn=p*3+3;
        edge[p*2+1].h=n;
        edge[p*2+1].c1=0.0;
        edge[p*2+1].c2=45.0;
        edge[p*2+1].fa=1;
        edge[p*2+2].h=m;
        edge[p*2+2].c1=45.0;
        edge[p*2+2].c2=90.0;
        edge[p*2+2].fa=0;
        sort(jiao+1,jiao+nn+1);
        for(int i=1;i<=nn;i++) {
            for(int j=i+1;j<=nn;j++) {
                if(fabs(jiao[i]-jiao[j])<1e-9) {
                    for(int k=j;k<nn;k++)
                        jiao[k]=jiao[k+1];
                    j--;
                    nn--;
                }
            }
        }
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=nn;i++) {
            vmax[i]=99999999.0;
        }
        for(int i=1;i<nn;i++) {
            double gg1=jiao[i];
            double gg2=jiao[i+1];
            for(int j=1;j<=p*2+2;j++) {
                if(edge[j].h!=0&&edge[j].c1<=gg1&&edge[j].c2>=gg2) {
                    double ss;
                    if(gg1==0.0) {
                        ss=edge[j].h*tan(gg2/pp)*edge[j].h/2.0;
                    }
                    if(gg2==90.0) {
                        ss=edge[j].h/tan(gg1/pp)*edge[j].h/2.0;
                    }
                    if(gg1!=0.0&&gg2!=90.0) {
                        if(edge[j].fa==0) ss=fabs(edge[j].h/tan(gg2/pp)-edge[j].h/tan(gg1/pp))*edge[j].h/2.0;
                        else ss=fabs(edge[j].h*tan(gg2/pp)-edge[j].h*tan(gg1/pp))*edge[j].h/2.0;
                    }
                    if(ss<vmax[i]) {
                        vmax[i]=ss;
                        vis[i]=j;
                    }
                }
            }
        }
        ans1=0;
        for(int i=1;i<nn;i++) {
            ans1+=vmax[i];
        }
        if(sa==0) ans1=0;



        sa=1;
        for(int i=1;i<=p;i++) {
            x2=n-ex1[i];x1=n-ex2[i];y2=m-ey1[i];y1=m-ey2[i];
            if(x1==0&&y1==0) {
                sa=0;
                break;
            }
            edge[i*2-1].h=x1;
            edge[i*2-1].fa=1;
            edge[i*2].h=y1;
            edge[i*2].fa=0;
            if(x1!=0) edge[i*2-1].c1=atan(y1/x1)*pp; else edge[i*2-1].c1=90.0;
            if(x1!=0) edge[i*2-1].c2=atan(y2/x1)*pp; else edge[i*2-1].c2=90.0;
            if(x2!=0) edge[i*2].c1=atan(y1/x2)*pp; else edge[i*2].c1=90.0;
            if(x1!=0) edge[i*2].c2=atan(y1/x1)*pp; else edge[i*2].c2=90.0;
            jiao[i*3-2]=edge[i*2-1].c1;
            jiao[i*3-1]=edge[i*2-1].c2;
            jiao[i*3]=edge[i*2].c1;
        }
        jiao[p*3+1]=0.0;
        jiao[p*3+2]=90;
        jiao[p*3+3]=45.0;
        nn=p*3+3;
        edge[p*2+1].h=n;
        edge[p*2+1].c1=0.0;
        edge[p*2+1].c2=45.0;
        edge[p*2+1].fa=1;
        edge[p*2+2].h=m;
        edge[p*2+2].c1=45.0;
        edge[p*2+2].c2=90.0;
        edge[p*2+2].fa=0;
        sort(jiao+1,jiao+nn+1);
        for(int i=1;i<=nn;i++) {
            for(int j=i+1;j<=nn;j++) {
                if(fabs(jiao[i]-jiao[j])<1e-9) {
                    for(int k=j;k<nn;k++)
                        jiao[k]=jiao[k+1];
                    j--;
                    nn--;
                }
            }
        }
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=nn;i++) {
            vmax[i]=99999999.0;
        }
        for(int i=1;i<nn;i++) {
            double gg1=jiao[i];
            double gg2=jiao[i+1];
            for(int j=1;j<=p*2+2;j++) {
                if(edge[j].h!=0&&edge[j].c1<=gg1&&edge[j].c2>=gg2) {
                    double ss;
                    if(gg1==0.0) {
                        ss=edge[j].h*tan(gg2/pp)*edge[j].h/2.0;
                    }
                    if(gg2==90.0) {
                        ss=edge[j].h/tan(gg1/pp)*edge[j].h/2.0;
                    }
                    if(gg1!=0.0&&gg2!=90.0) {
                        if(edge[j].fa==0) ss=fabs(edge[j].h/tan(gg2/pp)-edge[j].h/tan(gg1/pp))*edge[j].h/2.0;
                        else ss=fabs(edge[j].h*tan(gg2/pp)-edge[j].h*tan(gg1/pp))*edge[j].h/2.0;
                    }
                    if(ss<vmax[i]) {
                        vmax[i]=ss;
                        vis[i]=j;
                    }
                }
            }
        }
        ans2=0;
        for(int i=1;i<nn;i++) {
            ans2+=vmax[i];
        }
        if(sa==0) ans2=0;



        sa=1;
        for(int i=1;i<=p;i++) {
            x2=n-ex1[i];x1=n-ex2[i];y1=ey1[i];y2=ey2[i];
            if(x1==0&&y1==0) {
                sa=0;
                break;
            }
            edge[i*2-1].h=x1;
            edge[i*2-1].fa=1;
            edge[i*2].h=y1;
            edge[i*2].fa=0;
            if(x1!=0) edge[i*2-1].c1=atan(y1/x1)*pp; else edge[i*2-1].c1=90.0;
            if(x1!=0) edge[i*2-1].c2=atan(y2/x1)*pp; else edge[i*2-1].c2=90.0;
            if(x2!=0) edge[i*2].c1=atan(y1/x2)*pp; else edge[i*2].c1=90.0;
            if(x1!=0) edge[i*2].c2=atan(y1/x1)*pp; else edge[i*2].c2=90.0;
            jiao[i*3-2]=edge[i*2-1].c1;
            jiao[i*3-1]=edge[i*2-1].c2;
            jiao[i*3]=edge[i*2].c1;
        }
        jiao[p*3+1]=0.0;
        jiao[p*3+2]=90;
        jiao[p*3+3]=45.0;
        nn=p*3+3;
        edge[p*2+1].h=n;
        edge[p*2+1].c1=0.0;
        edge[p*2+1].c2=45.0;
        edge[p*2+1].fa=1;
        edge[p*2+2].h=m;
        edge[p*2+2].c1=45.0;
        edge[p*2+2].c2=90.0;
        edge[p*2+2].fa=0;
        sort(jiao+1,jiao+nn+1);
        for(int i=1;i<=nn;i++) {
            for(int j=i+1;j<=nn;j++) {
                if(fabs(jiao[i]-jiao[j])<1e-9) {
                    for(int k=j;k<nn;k++)
                        jiao[k]=jiao[k+1];
                    j--;
                    nn--;
                }
            }
        }
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=nn;i++) {
            vmax[i]=99999999.0;
        }
        for(int i=1;i<nn;i++) {
            double gg1=jiao[i];
            double gg2=jiao[i+1];
            for(int j=1;j<=p*2+2;j++) {
                if(edge[j].h!=0&&edge[j].c1<=gg1&&edge[j].c2>=gg2) {
                    double ss;
                    if(gg1==0.0) {
                        ss=edge[j].h*tan(gg2/pp)*edge[j].h/2.0;
                    }
                    if(gg2==90.0) {
                        ss=edge[j].h/tan(gg1/pp)*edge[j].h/2.0;
                    }
                    if(gg1!=0.0&&gg2!=90.0) {
                        if(edge[j].fa==0) ss=fabs(edge[j].h/tan(gg2/pp)-edge[j].h/tan(gg1/pp))*edge[j].h/2.0;
                        else ss=fabs(edge[j].h*tan(gg2/pp)-edge[j].h*tan(gg1/pp))*edge[j].h/2.0;
                    }
                    if(ss<vmax[i]) {
                        vmax[i]=ss;
                        vis[i]=j;
                    }
                }
            }
        }
        ans4=0;
        for(int i=1;i<nn;i++) {
            ans4+=vmax[i];
        }
        if(sa==0) ans4=0;
        printf("%.6f %.6f\n",ans1,ans2);
        printf("%.6f %.6f\n",ans3,ans4);
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值