LA 4253 Archery -

题目地址:http://vjudge.net/problem/UVALive-4253

二分x轴上的点,再用角度的区间表示能否射到

#include <bits/stdc++.h>
using namespace std;
#define REP(i,a,b)  for(int i=a;i<=(int)(b);++i)
#define REPD(i,a,b) for(int i=a;i>=(int)(b);--i)
const double EPS=1e-6;
struct Target
{
	double d,l,r;
	bool operator < (const Target& t) const {
		return d<t.d;
	}
}tt[5000+5];
int n,w;
int Check(double x){
	double L=atan2(tt[1].d,tt[1].r-x);  //[L,R]  因为是逆时针的
	double R=atan2(tt[1].d,tt[1].l-x);
	REP(i,2,n){
		double L1=atan2(tt[i].d,tt[i].r-x);
		double R1=atan2(tt[i].d,tt[i].l-x);
		if(L-R1>EPS) return -1;  //[L,R] U [L1,R1] != 空集
		if(L1-R>EPS) return 1;
		L=max(L,L1);
		R=min(R,R1);
	}
	return 0;
}
int main(int argc, char const *argv[])
{
	int T; scanf("%d",&T);
	while(T--){
		scanf("%d%d",&w,&n);
		REP(i,1,n) scanf("%lf%lf%lf",&tt[i].d,&tt[i].l,&tt[i].r);
		sort(tt+1,tt+1+n);
		bool ok=false;
		double L=0,R=w;
		while(R-L>EPS){
			double mid=(L+R)/2;
			int a=Check(mid);
			if(a==0) {ok=true; break;}
			else if(a==-1) R=mid;      //点要向左边移动
			else L=mid;
		}
		printf("%s\n", ok?"YES":"NO");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值