Gym - 101480I[思维题乱搞]

版权声明:欢迎随便转载。 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;
} 

猜你喜欢

转载自blog.csdn.net/a1214034447/article/details/89856773