LA 4253 Archery 二分
2015-12-23 15:10
260 查看
题意:
x轴上方有若干条平行于x轴的线段在x轴的区间\([0, \, W]\)内找一点发射一条射线,使其穿过所有线段。
问是否存在这样的点。
分析:
我们二分射线端点的坐标,将线段按纵坐标从小到大排序,维护一个可以穿过所有线段的极角区间。如果该区间为空说明这个点不符合要求,我们可以根据扫描到的最后一条线段来调整出射点的位置。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <iomanip> #include <cmath> using namespace std; const int maxn = 5000 + 10; typedef long double LD; const LD eps = 1e-10; int dcmp(LD x) { if(fabs(x) < eps) return 0; return x < 0 ? -1 : 1; } struct Segment { LD y, l, r; void read() { cin >> y >> l >> r; } bool operator < (const Segment& a) const { return y < a.y; } }; int n; LD W; Segment seg[maxn]; int check(LD x) { LD L = atan2(seg[0].y, seg[0].r - x); LD R = atan2(seg[0].y, seg[0].l - x); for(int i = 1; i < n; i++) { LD l = atan2(seg[i].y, seg[i].r - x); LD r = atan2(seg[i].y, seg[i].l - x); if(dcmp(l - R) > 0) return 1; if(dcmp(r - L) < 0) return -1; L = max(L, l); R = min(R, r); } return 0; } int main() { //freopen("4253.txt", "r", stdin); int T; scanf("%d", &T); while(T--) { cin >> W; scanf("%d", &n); for(int i = 0; i < n; i++) seg[i].read(); sort(seg, seg + n); double L = 0, R = W; bool ok = false; for(int i = 0; i < 100; i++) { LD mid = (L + R) / 2; int t = check(mid); if(t == 1) L = mid; else if(t == -1) R = mid; else { ok = true; break; } } printf("%s\n", ok ? "YES" : "NO"); } return 0; }
相关文章推荐
- 你还需要除PHP之外的编程语言吗(2)
- 手机自动化测试:Appium源码分析之跟踪代码分析一 2
- 第十章 会话管理
- LeetCode 38:Count and Say
- Android编译系统参考手册
- 手机自动化测试:Appium源码分析之跟踪代码分析一 1
- Summernote
- 类别(Categories)和扩展/匿名类别(extensions)及其延伸使用
- django常用函数
- 设计模式C++实现--状态模式
- 常见的块状元素与内联元素
- [程序设计语言-实践之路]读书笔记(1)
- stay hungry ,stay foolish!
- 云计算推动互联网金融技术性变革 打造专业安全的金融解决方案
- asp.net文件压缩,下载,物理路径,相对路径,删除文件
- 存储过程实现报表数据源的利弊分析
- 如何获取(GET)一杯咖啡——星巴克REST案例分析
- 第九章-----jsp标签
- 线上引流压测工具Meteor
- 手机自动化测试:Appium源码之API(2)