暴力求圆的面积并

2023-11-04 06:20
文章标签 面积 暴力 求圆

本文主要是介绍暴力求圆的面积并,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:
这个问题是集训时看到这道题后,再想要着手学习的。本篇中给出的做法复杂度并不能完全通过本题。
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
时限:7S,空间限制:512M

解法:

首先画图:

在这里插入图片描述
可以发现圆的面积并等于中间一些多边形(不一定是凸的)的面积+每个圆未被其它圆所覆盖的弓形的面积。所以就对于每个圆,求出其被覆盖的圆弧部分,这些部分形成了一些区间,然后先把区间合并起来,然后就可以叉积求出每个圆的被覆盖的多边形面积和未被覆盖的弓形面积。

#include <bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
const int maxn=2005;
inline int read(){char c=getchar();int t=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}return t*f;
}
double rs,rb;
int ns,nb,t;
struct node{double x,y;node(double xx=0,double yy=0){x=xx,y=yy;}
}a[maxn];
node operator +(node a,node b){return node(a.x+b.x,a.y+b.y);}
node operator -(node a,node b){return node(a.x-b.x,a.y-b.y);}
double operator *(node a,node b){return a.x*b.x+a.y*b.y;}
node operator *(node a,double b){return node(a.x*b,a.y*b);}
node operator /(node a,double b){return node(a.x/b,a.y/b);}
double cross(node a,node b){return a.x*b.y-a.y*b.x;}
double dist(node a,node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
struct data{node ax,ay;double x,y;
}c[maxn];
double R[maxn];
int cho[maxn],alfa[maxn];
int n,b[maxn],m,l;
double ans1,ans2;
bool operator <(data a,data b){return (a.x<b.x)||((a.x==b.x)&&(a.y<b.y));
}
inline node rot(node p,double a){return node(cos(a)*p.x-sin(a)*p.y,sin(a)*p.x+cos(a)*p.y);
}
inline double deg(node p){double tmp=atan2(p.y,p.x);return tmp<0?tmp+2*pi:tmp;
}
inline void work(node o1,node o2,double r1,double r2){double s,p,h,alfa,tmp=dist(o1,o2);p=(r1+r2+tmp)/2;s=sqrt(p*(p-r1)*(p-r2)*(p-tmp));//海伦公式求面积 h=s*2/tmp;alfa=asin(h/r1);//h:高,alfa:夹角 if(r1*r1+tmp*tmp<r2*r2)alfa=pi-alfa;//如果是钝角 m++;c[m].ax=rot(o2-o1,pi*2-alfa)/tmp*r1+o1;//求交点 c[m].ay=rot(o2-o1,alfa)/tmp*r1+o1;c[m].x=deg(c[m].ax-o1);//求出两个交点的极角 c[m].y=deg(c[m].ay-o1);if(c[m].x>c[m].y){//如果两个交点形成的弧跨过了2pi,就需要把弧拆成两段。 m++;c[m].y=c[m-1].y;c[m].ay=c[m-1].ay;c[m-1].y=pi*2;c[m].x=0;c[m-1].ay=c[m].ax=o1+node(r1,0);}
}
int main() {//freopen("c.in","r",stdin);//freopen("c.out","w",stdout);scanf("%lf%lf",&rs,&rb);t=read();while(t--){ns=read();nb=read();n=ns+nb;for(int i=1;i<=ns;i++){a[i].x=read();a[i].y=read();R[i]=rs;}for(int i=ns+1;i<=ns+nb;i++){a[i].x=read(),a[i].y=read();R[i]=rb;}if(ns+nb==1){if(nb)printf("%.3lf\n",pi*rb*rb);else printf("%.3lf\n",pi*rs*rs);continue;}memset(b,0,sizeof(b));for(int i=1;i<=n;i++){if(!b[i]){for(int j=1;j<=n;j++){if((!b[j])&&(i!=j)&&(dist(a[i],a[j])<=R[j]-R[i])){//	printf("%d %d %lf %lf %lf %lf\n",i,j,a[i].x,a[i].y,a[j].x,a[j].y);b[i]=1;break;}}}}ans1=ans2=0;for(int i=1;i<=n;i++){if(!b[i]){m=0;for(int j=1;j<=n;j++){if((!b[j])&&(i!=j)&&dist(a[i],a[j])<=R[j]+R[i]){work(a[i],a[j],R[i],R[j]);}}if(m==0){ans2+=pi*R[i]*R[i];continue;}sort(c+1,c+1+m);c[0].y=0;c[m+1].x=pi*2;c[0].ay=c[m+1].ax=a[i]+node(R[i],0);double tmp=0;int k;for(int j=0;j<=m;j=k+1){for(k=l=j;k<m&&c[k+1].x<=c[l].y;k++){if(c[k+1].y>c[l].y) l=k+1;}ans1+=cross(c[l].ay,c[k+1].ax);tmp=c[k+1].x-c[l].y;ans2+=R[i]*R[i]*(tmp-sin(tmp))/2;}}}printf("%.5lf\n",fabs(ans1)/2+ans2);}return 0;
}

其实思路并不是很难,但是实现起来比较麻烦。时间复杂度 O ( t × n 2 l o g n ) O(t\times n^2logn) O(t×n2logn)

这篇关于暴力求圆的面积并的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/343860

相关文章

计蒜客 Half-consecutive Numbers 暴力打表找规律

The numbers 11, 33, 66, 1010, 1515, 2121, 2828, 3636, 4545 and t_i=\frac{1}{2}i(i+1)t​i​​=​2​​1​​i(i+1), are called half-consecutive. For given NN, find the smallest rr which is no smaller than NN

10125-Sumsets【暴力】

利用n^2的时间枚举所有a[i] + a[j] 利用n^2的时间枚举所有a[i] - a[j] 之后利用n^2时间一个一个找a[i] - a[j]的值是否存在于a[i] + a[j]中 找的时候需要二分查找 另外一点就是注意long long的范围以及四个数是集合内不同的四个元素 15222638 10125 Sumsets Accepted C++ 0.449 2015-03-

10730-Antiarithmetic?【暴力枚举】

水题 求一个序列是否存在3个数按顺序构成等差数列 直接枚举等差数列的差值 时间复杂度降到 n * n / 3 开pos数组记录每个值得为之 楷vis数组记录目前i是否出现过 强行AC 15221397 10730 Antiarithmetic? Accepted C++ 0.035 2015-03-26 12:09:56 #include<cstdio>#include

HLJUOJ1125(暴力三点一线)

两点确定一条直线 Time Limit: 1 Sec   Memory Limit: 128 MB Submit: 19   Solved: 11 [ Submit][ Status][ Web Board] Description  给一个15000 * 15000 的区域, 坐标都是整数. 其中有N个点,N <= 770.问总共有多少个3点共线的组合.并按升序(点的ID)输出

HLJUOJ1117(暴力模拟)

八数码 Time Limit: 1 Sec   Memory Limit: 128 MB Submit: 109   Solved: 19 [ Submit][ Status][ Web Board] Description 给定一个8数码的初始状态,然后给出一系列对8数码的操作,求其最终状态. Input 第一行t,代表样例个数。 每组数据前三行各三个数,代表八数

CF Bayan 2015 Contest Warm Up B.(dfs+暴力)

B. Strongly Connected City time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/475/probl

UVA10010(八方向暴力枚举)

Where's Waldorf? Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu 题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18656 Description Where's Waldo

CF #278 (Div. 2) B.(暴力枚举+推导公式+数学构造)

B. Candy Boxes time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/488/problem/B There

CF#278 (Div. 2) A.(暴力枚举)

A. Giga Tower time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/488/problem/A Giga To

CF#284 (Div. 2) B.(暴力)

题目链接:http://codeforces.com/contest/499/problem/B 解题思路: 开一个is变量记录每组单词最后应该输出哪个。最后每次把原来的数组暴力扫一遍即可。 完整代码: #include <functional>#include <algorithm>#include <iostream>#include <fstream>#inc