题目大致意思是一个矩形,里面有很多小矩形,小矩形是障碍物,问在四个角上能看到的范围面积。
解题思路:
因为障碍物只有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;
}