直接暴力搞可以过,具体题解参考:http://blog.csdn.net/u012997373/article/details/39521035
感谢这位博主让我查到了错误,其他都写对了,就判断两线段是否相交那里出错了,查了整整2天....
我有两份代码,一份是暴力的,一份是用数据结构优化的。既然大家都是用暴力过的,那我就贴数据结构优化的。(秉着每道水题都当做大数据题来做的心态...
暴力过,时间1.5s-1.8s,数据结构优化:450ms左右,显然,快了一个级别。
代码如下:
//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi acos(-1.0)
#define eps 1e-6
#define MOD 1000000007
#define MAXN 50100
#define N 300100
#define M 10100
struct Point
{
double x,y;
Point(){};
Point(double xx,double yy):x(xx),y(yy){};
}sensor[N],wall1[100],wall2[100];
typedef Point Vector;
void readPoint(Point &a){//输入一个点
scanf("%lf %lf",&a.x,&a.y);
}
double sq(double x){//x^2
return x*x;
}
int dcmp(double x){//判断x正负或为0
if(fabs(x)<eps) return 0;
else if(x<0) return -1;
else return 1;
}
Vector operator +(const Vector a,const Vector b){//两向量相加
return Vector(a.x+b.x,a.y+b.y);
}
Vector operator -(const Vector a,const Vector b){//两向量相减
return Vector(a.x-b.x,a.y-b.y);
}
bool operator ==(const Vector a,const Vector b){//判断两点或两向量是否一致
return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
}
double operator *(const Vector a,const Vector b){//两向量点乘
return a.x*b.x+a.y*b.y;
}
double operator &(const Vector a,const Vector b){//两向量叉积
return a.x*b.y-a.y*b.x;
}
Vector operator *(const Vector b,const double a){//一个数*一个向量
return Vector(a*b.x,a*b.y);
}
Vector operator *(const double a,const Vector b){//一个向量*一个数
return Vector(a*b.x,a*b.y);
}
double Length(Vector b){//求一个向量的长度
return sqrt(b*b);
}
double DistancePointToPoint(Point a,Point b){//求点到点的无向距离
return Length(a-b);
}
bool SegmentBananaSegment(Point p1,Point p2,Point w1,Point w2){//判断两线段是否香蕉
if (fmin (p1.x, p2.x) > fmax (w1.x, w2.x) ||
fmin (p1.y, p2.y) > fmax (w1.y, w2.y) ||
fmin (w1.x, w2.x) > fmax (p1.x, p2.x) ||
fmin (w1.y, w2.y) > fmax (p1.y, p2.y))
return false;
double x1=(w2-w1)&(p1-w1);
double x2=(w2-w1)&(p2-w1);
double x3=(p2-p1)&(w1-p1);
double x4=(p2-p1)&(w2-p1);
return dcmp(x1*x2)<=0 && dcmp(x3*x4)<=0;
}
//Circle
struct Circle
{
Point c;
double r;
Circle(){};
Circle(Point c,double r):c(c),r(r){};
Point point(double a){
return Point(c.x+cos(a)*r,c.y+sin(a)*r);
}
};
void readCircle(Circle &c1,Point p,double r){//输入一个圆
c1.c=p;
c1.r=r;
}
int LineBananaCircle(Point p,Vector v,Circle c,vector<Point>&poi){//求一条线和一个圆的交点。三种情况
double a1=v.x,b1=p.x-c.c.x,c1=v.y,d1=p.y-c.c.y;
double e1=sq(a1)+sq(c1),f1=2*(a1*b1+c1*d1),g1=sq(b1)+sq(d1)-sq(c.r);
double delta=sq(f1)-4*e1*g1,t;
if(dcmp(delta)<0) return 0;
else if(dcmp(delta)==0){
t=(-f1)/(2*e1);poi.pb(p+v*t);
return 1;
}
else{
t=(-f1+sqrt(delta))/(2*e1);poi.pb(p+v*t);
t=(-f1-sqrt(delta))/(2*e1);poi.pb(p+v*t);
return 2;
}
}
int num_sen,num_wall,num_pro;
double r;
vector<int>ycor[MAXN];
struct Data{
int x,y;
}d;
vector<Data>ans[MAXN];
bool comp(const Data a,const Data b){
if(a.x!=b.x) return a.x<b.x;
else return a.y<b.y;
}
void caculate_ans(vector<int>ycor[],int y,int k1,int k2,Point pro,int k){
repin(i,k1,k2){
sensor[0].y=y;
sensor[0].x=ycor[y][i];
int num_b=0;
repin(j,1,num_wall){
if(SegmentBananaSegment(pro,sensor[0],wall1[j],wall2[j])){
num_b+=1;
}
}
double rt=r-num_b;
double dis=DistancePointToPoint(sensor[0],pro);
if(dcmp(rt-dis)>=0){
d.x=(int)sensor[0].x-M;
d.y=(int)sensor[0].y-M;
ans[k].pb(d);
}
}
}
int main()
{
int T;
cin>>T;
while(T--){
scanf("%d %lf %d %d",&num_sen,&r,&num_wall,&num_pro);
repin(i,0,M<<1){
ycor[i].clear();
}
repin(i,1,num_sen){
readPoint(sensor[i]);
sensor[i].x+=M,sensor[i].y+=M;
int y=(int)sensor[i].y;
ycor[y].pb((int)sensor[i].x);
}
repin(i,0,M<<1){
int len=gsize(ycor[i]);
if(len>0){
sort(ycor[i].begin(),ycor[i].end());
}
}
repin(i,1,num_wall){
readPoint(wall1[i]);
wall1[i].x+=M,wall1[i].y+=M;
readPoint(wall2[i]);
wall2[i].x+=M,wall2[i].y+=M;
}
repin(i,1,num_pro){
ans[i].clear();
}
Point pro;
repin(i,1,num_pro){
readPoint(pro);
pro.x+=M,pro.y+=M;
repin(j,(int)(pro.y-r),(int)(pro.y+r)){
int leny=gsize(ycor[j]);
if(!leny) continue;
vector<Point>poi;
poi.clear();
Circle c;
readCircle(c,pro,r);
Point pt(pro.x-r,j);
Vector vt(1,0);
int num=LineBananaCircle(pt,vt,c,poi);
if(num==2){
Point p1=poi[0],p2=poi[1];
if(dcmp(p1.x-p2.x)>0) swap(p1,p2);
int x=(int)p1.x;
if(p1.x-x>0) p1.x=x+1;
p2.x=(int)p2.x;
int k1=(int)(lower_bound(ycor[j].begin(),ycor[j].end(),(int)p1.x)-ycor[j].begin());
int k2=(int)(upper_bound(ycor[j].begin(),ycor[j].end(),(int)p2.x)-ycor[j].begin())-1;
if(k1>k2) continue;
caculate_ans(ycor,j,k1,k2,pro,i);
}
else if(num==1){
Point p=poi[0];
int k1=(int)(lower_bound(ycor[j].begin(),ycor[j].end(),(int)p.x)-ycor[j].begin());
int k2=(int)(upper_bound(ycor[j].begin(),ycor[j].end(),(int)p.x)-ycor[j].begin())-1;
if(k1>k2) continue;
caculate_ans(ycor,j,k1,k2,pro,i);
}
}
}
repin(i,1,num_pro){
int len=gsize(ans[i]);
if(len>0){
sort(ans[i].begin(),ans[i].end(),comp);
}
printf("%d",len);
rep(j,0,len){
printf(" (%d,%d)",ans[i][j].x,ans[i][j].y);
}
printf("\n");
}
}
}