`

hdu3684

 
阅读更多

/*
刚开始打了个记录上下左右四个点的,一直tle。
研究了isun大牛的代码后发现原来可以更简单………… 
*/
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef double typev;
const int N=105;
const int Q=1005;
const int M=10005;
const double eps=1e-8;
const double pi=acos(-1.0);
int sign(double d){
	return d<-eps?-1:(d>eps);
}
struct point{
	typev x, y;
	point(double _x=0, double _y=0):x(_x), y(_y){}
	point operator-(point tp){
		return point(x-tp.x, y-tp.y);
	}
	double operator^(point tp){
		return x*tp.y-y*tp.x;
	}
	void read(){
		scanf("%lf%lf", &x, &y);
	}
}hull[N][Q], ps[Q];
struct ray{
	point st, v;
	double ang;
	int id;
	bool operator<(const ray& _ray)const{
		return ang<_ray.ang;
	}
};
int hn[N], n, m;
int ls[N], rs[N];
int ans[M];
ray rays[M];
bool cmp(point d1, point d2){
	return d1.x < d2.x || (d1.x == d2.x && d1.y < d2.y);
}
typev xmul(point st1, point ed1, point st2, point ed2){
	return (ed1.x-st1.x) * (ed2.y-st2.y) - (ed1.y-st1.y) * (ed2.x-st2.x);
}
//对ps求凸包,结果放在hull里
void graham(point* ps, int n, point* hull, int& hn){
	int i;
	if(n<=2){
		hn=n;
		for(i=0; i<n; i++){
			hull[i]=ps[i];
		}
		return;
	}
	sort(ps, ps+n, cmp);
	hull[0] = ps[0];
	hull[1] = ps[1];
	int top = 1;
	for(i = 2; i < n; i++){
		while(top > 0 && xmul(ps[i], hull[top-1], ps[i], hull[top]) >= 0) top--;
		hull[++top] = ps[i];
	}
	int tmp = top;
	for(i = n-2; i >= 0; i--){
		while(top > tmp && xmul(ps[i], hull[top-1], ps[i], hull[top]) >= 0) top--;
		hull[++top] = ps[i];
	}
	hn = top;
	hull[hn] = hull[0];
}
bool input(){
	scanf("%d", &n);
	int i, j, qn;
	for(i=0; i<n; i++){
		scanf("%d", &qn);
		for(j=0; j<qn; j++){
			ps[j].read();
		}
		graham(ps, qn, hull[i], hn[i]);
		//保证点是逆时针方向的
		reverse(hull[i], hull[i]+hn[i]);
	}
	scanf("%d", &m);
	for(i=0; i<m; i++){
		rays[i].st.read();
		rays[i].v.read();
		rays[i].id=i;
		rays[i].ang=atan2(rays[i].v.y, rays[i].v.x);
	}
	return true;
}
void solve(){
	sort(rays, rays+m);
	int i, j, u;
	point *h;
	point a, b, c, d;
	ray  r;
	for(i=0; i<n; i++){
		ls[i]=rs[i]=0;
	}
	for(i=0; i<m; i++){
		u=-1;
		r=rays[i];
		for(j=0; j<n; j++){
			h=hull[j];
			while((r.v^h[(ls[j]+1)%hn[j]]-h[ls[j]]) > 0){
				ls[j]=(ls[j]+1)%hn[j];
			}
			while((r.v^h[(ls[j]-1+hn[j])%hn[j]]-h[ls[j]]) > 0){
				ls[j]=(ls[j]-1+hn[j])%hn[j];
			}
			while((r.v^h[(rs[j]+1)%hn[j]]-h[rs[j]])<0){
				rs[j]=(rs[j]+1)%hn[j];
			}
			while((r.v^h[(rs[j]-1+hn[j])%hn[j]]-h[rs[j]])<0){
				rs[j]=(rs[j]-1+hn[j])%hn[j];
			}
			if((h[rs[j]]-h[ls[j]]^r.st-h[ls[j]])>0) continue;
			if(sign(r.v^h[ls[j]]-r.st)*sign(r.v^h[rs[j]]-r.st)>0) continue;
			if(u==-1){
				u=j;
			}else{
				a=h[ls[j]];
				b=h[rs[j]];
				c=hull[u][ls[u]];
				d=hull[u][rs[u]];
				if(((b-a^c-a)>0 && (b-a^c-a)>0) || ((d-c^a-c)<0 && (d-c^b-c)<0)){
					u=j;
				}
			}
		}
		ans[r.id]=u;
	}
	for(i=0; i<m; i++){
		if(ans[i]==-1){
			printf("MISS\n");
		}else{
			printf("HIT %d\n", ans[i]);
		}
	}
	printf("*****\n");
}
int main(){
//	freopen("in.txt", "r", stdin);
	int t;
	scanf("%d", &t);
	while(t--){
		input();
		solve();
	}
	return 0;
}
 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics