UVA 1421 UVALive 4253 Archery

5 篇文章 0 订阅

Time Limit:3000MS Memory Limit:Unknown 64bit IO Format:%lld & %llu

[]  [Go Back]  [Status]  

Description

Download as PDF

Korea's reputation in archery is well known because the Korean archery teams have been sweeping almost all gold, silver, and bronze medals in the Olympic Games.

An archery game ICPC supported by NEXON (one of Korea's leading publishers of online contents) will be held in Korea. As a ceremonial event of the game, a famous master of archery will shoot an arrow to hit through all target boards made of paper. Because an arrow flies along a straight line, it depends on his position of the archer line whether or not he hits all targets.

The figure below shows an example of the complete view of a game field from the sky. Every target is represented by a line segment parallel to the archer line. Imagine the coordinate system of which the origin is the leftmost point of the archer line and the archer line is located on the positive x -axis.

\epsfbox{p4253.eps}

In the above figure, the master can hit all targets in position B. However, he never hits all targets in positionA because any ray from A intersects at most 3 targets.

Given the width of the archer line and the target locations, write a program for determining if there exists a position at which the master can hit all targets. You may assume that they -coordinates of all targets are different. Note that if an arrow passes through an end point of a target, it is considered to hit that target.

Input

Your program is to read from standard input. The input consists of T test cases. The number of test cases T(1$ \le$T$ \le$30) is given in the first line of the input. Each test case starts with a line containing an integerW(2$ \le$W$ \le$10, 000, 000) , the width of an archer line. The next line contains an integerN(2$ \le$N$ \le$5, 000) , the number of target boards. The i -th line of the followingN lines contains three integers Di , Li ,Ri(1$ \le$Di$ \le$W, 0$ \le$Li <Ri$ \le$W) , where1$ \le$i$ \le$N , Di represents the y -coordinate of the i -th target, andLi and Ri represent thex -coordinates of the leftmost point and the rightmost point of the target, respectively. Note thatDi$ \neq$Dj ifi$ \neq$j .

Output

Your program is to write to standard output. Print exactly one line for each test case. Print ``YES" if there exists a position on the archer line at which a master of archery can hit all targets, otherwise, ``NO".

The following shows sample input and output for three test cases.

Sample Input

3 
15 
4 
10 2 7 
7 5 12 
2 7 12 
4 9 13 
6 
3 
2 1 3 
4 0 2 
5 4 6 
10 
4 
8 2 5 
4 2 5 
6 5 8 
2 5 8

Sample Output

YES 
NO 
YES

题意:有n个平行于x轴的线段,每条线段代表一个靶子。任务是判断是否可以站在x轴上的[0,W]区间内的某个点射箭,使得能够穿过所有靶子,不同靶子高度y不同


思路:

首先想一个问题:怎么判断站在一个点x射箭能否射穿所有靶子?

对于一个靶子i[Li,Ri],在x点要射穿他,那么箭的角度是一个区间

这样的话,直接求出每个靶子的角度区间,然后维护当前满足所有靶子的区间。

分析会发现其中一个特点,如果一个靶子的区间为[130, 145] 而当前区间为[90, 120] 则当前位置x不能射穿所有靶子。则x需要向做移动,反之向右移动。



#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define FOR(i, s, t) for(int (i)=(s); (i)<(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 5000 + 20;
int n;
double w;
struct Line {
    double d, l, r;
    bool operator < (const Line & b) const {
        return d < b.d;
    }
};
Line lines[maxn];

int judge(double p) {
    double L = 0;
    double R = INF;
    for(int i=0; i<n; i++) {
        double tL = atan2(lines[i].d, lines[i].r - p);
        double tR = atan2(lines[i].d, lines[i].l - p);
        if(L - tR > eps) return 0;
        if(tL - R > eps) return 1;
        L = max(L, tL);
        R = min(R, tR);
    }
    return 3;
}

int main() {
    int T;

    scanf("%d", &T);
    while(T--) {
        scanf("%lf%d", &w, &n);
        for(int i=0; i<n; i++) {
            scanf("%lf%lf%lf", &lines[i].d, &lines[i].l, &lines[i].r);
        }
        sort(lines, lines+n);
        int ans = 0;
        double L=0, R=w;
        while(R - L > eps) {
            double mid = (L + R) / 2;
            int res = judge(mid);
            if(res == 3) {
                ans = 1;
                break;
            } else if(res == 1) L = mid;
            else R = mid;
        }
        if(ans) puts("YES");
        else puts("NO");
    }

    return 0;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值