版权声明:欢迎随便转载。 https://blog.csdn.net/a1214034447/article/details/89856773
题目链接:https://vjudge.net/problem/Gym-101480I
解题思路:
首先题目保证圆不会相交,而且圆的半径都是小于1的所以给定一个圆只会有四个单元格包含它,并且线段经过单元也不会超过n+m<=500+500<=1000.
所以对于每个线段,去暴力它经过的每个单元格,然后在询问与该单元格相交的圆是否与线段的距离小于等于r,如果满足条件还要讲该圆标记,因为线段最多只经过1000个单元格所以被标记的圆也最多不会超过1000次。
所以最后的时间复杂度O(m*1000*4)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = 1e5 + 10;
const int N = 501;
int n,m,q[mx],hd;
int g[3*mx][5],siz[3*mx];
double r[mx];
bool vis[mx];
struct node
{
int x,y;
}s[mx];
int gety(node A,node B,int x)
{
double ret = 1.0*(x-A.x)*(B.y-A.y)/(B.x-A.x) + A.y;
return floor(ret);
}
double dist(node w,node A,node B)//点到线段距离
{
double cross = (B.x - A.x) * (w.x - A.x) + (B.y - A.y) * (w.y - A.y);
if (cross <= 0)
return (w.x - A.x) * (w.x - A.x) + (w.y - A.y) * (w.y - A.y);
double d2 = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y);
if (cross >= d2)
return (w.x - B.x) * (w.x - B.x) + (w.y - B.y) * (w.y - B.y);
double r = cross / d2;
double px = A.x + (B.x - A.x) * r;
double py = A.y + (B.y - A.y) * r;
return (w.x - px) * (w.x - px) + (w.y - py) * (w.y - py);
}
int cal(int u,node A,node B)
{
int ans = 0,len = siz[u];
for(int j=0;j<len;j++){
int i = g[u][j];
if(!vis[i]&&dist(s[i],A,B)<=r[i]){
ans++;
vis[i] = 1;
q[hd++] = i;
}
}
return ans;
}
int main()
{
scanf("%d",&n);
int d;
for(int i=1;i<=n;i++){
scanf("%d%d%lf",&s[i].x,&s[i].y,r+i);
r[i] *= r[i];
d = s[i].x*N+s[i].y;g[d][siz[d]++] = i;
d = s[i].x*N+s[i].y-1;g[d][siz[d]++] = i;
d = (s[i].x-1)*N+s[i].y;g[d][siz[d]++] = i;
d = (s[i].x-1)*N+s[i].y-1;g[d][siz[d]++] = i;
}
scanf("%d",&m);
node A,B;
while(m--){
scanf("%d%d%d%d",&A.x,&A.y,&B.x,&B.y);
int ans = 0;hd = 0;
if(A.x>B.x) swap(A,B);
int x1 = A.x,x2 = B.x,y1 = A.y,y2 = B.y;
if(y1<y2){
while(x1!=x2){
int y = gety(A,B,x1+1);
while(y1<y) ans += cal(x1*N+y1,A,B),y1++;
ans += cal(x1*N+y1,A,B);
x1++;
}
while(y1<=y2) ans += cal(x2*N+y1,A,B),y1++;
}else{
while(x1!=x2){
int y = gety(A,B,x1+1);
while(y1>y) ans += cal(x1*N+y1,A,B),y1--;
ans += cal(x1*N+y1,A,B);
x1++;
}
while(y1>=y2) ans += cal(x2*N+y1,A,B),y1--;
}
printf("%d\n",ans);
for(int i=0;i<hd;i++) vis[q[i]] = 0;
}
return 0;
}