因为数据范围不大,避免重复计数,使用一个数组直接标记法即可。
是否在圆内的判断使用到圆心的距离,遍历范围x±r,y±r,是否在正方形内直接判断,数据范围x->x+r,y->y+r,是否在三角形内部,需要用到一定的数学知识,一般有以下两种方法,一是利用面积来判断,对于三角形ABC,任取一个点M,连接M与ABC三个顶点,构成了三个三角形,三个三角形的和若等于原三角形的和,则在内部,否则在外部,但是利用海伦公式求面积时,浮点数会引起误差,一般推荐使用另一种方法,即是计算MA*MB、MB*MC、MC*MA的大小,若这三个值同号,那么在三角形的内部,异号在外部,本文代码使用第二种方法,避免了浮点数的运算 。
避免在遍历圆内的点时出现负数,例如(x,y)=(1,1),r=3,所有输入均加上100即可。
get新的知识,利用叉乘判断某点是否在三角形里面
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
struct node
{
int x, y;
}a1, b1, c1, d1;
int mul(struct node a, struct node b, struct node c)// 计算向量AB 与向量AC的叉乘
{
return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}
int judge(int i, int j)//如果DA*DB、DB*DC、DC*DA同号,则在三角形内部
{
d1.x = i;
d1.y = j;
int t1 = mul(d1, a1, b1);
int t2 = mul(d1, b1, c1);
int t3 = mul(d1, c1, a1);
if(t1>=0&&t2>=0&&t3>=0)
return 1;
if(t1<=0&&t2<=0&&t3<=0)
return 1;
return 0;
}
int v[212][212];//判断此点是否在里面
int main()
{
int T, t;
cin>>T;
while(T--)
{
memset(v, 0, sizeof(v));//清零
cin>>t;
int count = 0;//个数
while(t--)
{
char m[121];
cin>>m;
if(m[0]=='S')//正方形
{
int a, b, c;
cin>>a>>b>>c;
a += 100;//避免坐标为负数
b += 100;
for(int i=a;i<=a+c;i++)//两层循环判断
{
for(int j=b;j<=b+c;j++)
{
if(!v[i][j])
{
count++;
v[i][j] = 1;
}
}
}
}
else if(m[0]=='T')//三角形,叉乘
{
cin>>a1.x>>a1.y>>b1.x>>b1.y>>c1.x>>c1.y;
a1.x += 100;
a1.y += 100;
b1.x += 100;
b1.y += 100;
c1.x += 100;
c1.y += 100;
for(int i=100;i<=200;i++)
{
for(int j=100;j<=200;j++)
{
if(!v[i][j]&&judge(i, j))
{
count++;
v[i][j] = 1;
}
}
}
}
else if(m[0]=='C')//圆,利用两点之间的距离判断
{
int a, b, c;
cin>>a>>b>>c;
a += 100;
b += 100;
for(int i=a-c;i<=a+c;i++)
{
for(int j=b-c;j<=b+c;j++)
{
if(!v[i][j]&&((a-i)*(a-i)+(b-j)*(b-j)<=c*c))
{
count++;
v[i][j] = 1;
}
}
}
}
}
cout<<count<<endl;
}
return 0;
}
本文介绍了一种通过遍历和标记法解决平面几何图形覆盖问题的算法。具体涉及如何判断点是否位于正方形、三角形及圆形内部的方法,并提供了一种避免浮点数运算误差的技巧。对于三角形,采用叉乘判断点的位置;对于圆形,利用距离判断;对于正方形,直接进行边界判断。
753

被折叠的 条评论
为什么被折叠?



