poj 2074
来源:互联网 发布:软件测试难学吗 编辑:程序博客网 时间:2024/05/29 16:17
题目概述
有一座房子建在道路旁边且和道路隔着一段距离,房主希望路人能完整看到房子朝向道路的那一面,但房子和道路之间隔着有一些障碍物,如果将道路,房子,障碍物都视为平行于x轴的线段,给定这些线段端点的坐标,求道路上最长的一段路使得路人可以完整的看到房子的正面
障碍物不会和房子相交,但可能和房子共线
时限
1000ms/3000ms
输入
第一行三个非负浮点数hx1,hx2,hy,描述房子线段的左端点横坐标,右端点横坐标,纵坐标,第二行三个非负浮点数lx1,lx2,ly,类似的描述道路,第三行正整数N,代表障碍物数,其后N行,每行三个浮点数x1,x2,y,类似的描述障碍物,输入到hx1=hx2=hy=0结束
限制
所有左端点横坐标<右端点横坐标;hy>ly
输出
每组数据在一行中输出,若存在符合条件的路,输出一个保留两位的浮点数,代表其最长长度,若从路的任何位置都无法完整看到房子正面,输出字符串
No View
样例输入
2 6 6
0 15 0
3
1 2 1
3 4 1
12 13 11 5 5
0 10 0
1
0 15 12 6 6
0 12 0
3
1 2 1
3 4 1
12 13 12 6 6
6 15 0
3
1 2 1
3 4 1
12 13 12 6 6
0 15 0
3
1 2 -1
3 4 -1
12 13 -12 6 6
0 15 0
3
1 2 10
3 4 10
12 13 102 6 6
0 15 0
02 6 6
0 15 0
1
0 15 10 0 0
样例输出
8.80
No View
7.60
7.20
15.00
15.00
15.00
15.00
No View
讨论
计算几何,求直线与直线交点,外加一点贪心(可能吧),先抛开各种坑不谈,计算视线,就是过房子左端点和障碍物右端点做直线,然后过房子右端点和障碍物左端点做直线,两条直线和路所在直线交与两点,这两点之间都算盲区,为啥?额只能说找张纸或者用几何画板画画就能看出来,求得一堆盲区后按左端点升序排序,然后根据右端点位置找出非盲区,考察相邻的两段盲区,如果下一个的左端点在上一个的右端点左侧,这两段盲区会覆盖成一个大盲区,记录一下右端点位置,否则,上一个的右端点到下一个的左端点之间就是一段非盲区,更新一下最大值,然后同样视为一个大盲区,记录大盲区右端点位置,到最后就会得到最大的一段非盲区长度
再来看一些坑点,题目说障碍物会和房子共线的时候已经有提醒了,显然只有房子和道路之间的障碍物会遮挡视线,于是将不在这个范围的障碍物遮挡的范围设为一个微小(0)的且绝对不在路上(-INF)的位置,第5,6组数据可以测试这一点,另外需要注意盲区的端点可能会落在路的外面,在路外面的一段是不能算的,通过比较端点和路端点位置关系可以解决,第3,4组数据可以测试这一点,再有就是对于没有障碍物的情况,由于这样就不会计算盲区位置,会导致输出无视野,因而可以人为添加两段盲区,把路的端点两侧覆盖,强制计算出一段非盲区(整条路),第7组数据可以测试这一点
另外题目也没说数据规模,额猜的100,竟然够了
题解状态
192K,0MS,C++,1735B
题解代码
#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;#define INF 0x3f3f3f3f #define MAXN 103#define memset0(a) memset(a,0,sizeof(a))#define EPS 1e-6struct Blocked//盲区结构{ double x1, x2;//左右端点横坐标 bool operator<(Blocked &b)const { return x1 < b.x1; }}block[MAXN];int N;//障碍物数double hx1, hx2, hy, lx1, lx2, ly;//house 房子的左右端点横坐标和纵坐标 line 道路的int signal(double a)//符号函数 这东西越来越好用{ if (abs(a) < EPS) return 0; else if (a > 0) return 1; else return -1;}double point_of_intersection_x(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)//求直线交点横坐标 点3点4是留给路的 由于路一定是水平 因而简单不少{ if (!signal(x1 - x2)) return x1; double k1 = (y2 - y1) / (x2 - x1); return (y1 - y3 - k1*x1) / (-k1);//解方程去 不要空想}void fun(){ block[N].x1 = -INF, block[N].x2 = lx1; block[N + 1].x1 = lx2, block[N + 1].x2 = INF;//人为添加的两段盲区 防止没有障碍物的情况 for (int p = 0; p < N; p++) { double x1, x2, y; scanf("%lf%lf%lf", &x1, &x2, &y);//input//一边读数 顺手算出交点 if (signal(hy - y) != 1 || signal(y - ly) != 1) {//无关紧要的障碍物位置 block[p].x1 = block[p].x2 = -INF;//虽说写0也能过 但是谨慎起见 还是扔远一点 continue; } block[p].x2 = point_of_intersection_x(hx1, hy, x2, y, lx1, ly, lx2, ly); block[p].x1 = point_of_intersection_x(hx2, hy, x1, y, lx1, ly, lx2, ly);//求得两个交点 } sort(block, block + N + 2);//排序 包含了两个额外盲区 double most = -INF, right = block[0].x2;//最长的非盲区长度 盲区右端点位置 以第一段初始化 方便后面处理 for (int p = 1; p < N + 2; p++) { if (block[p].x1 > block[p - 1].x2)//如果下一个的左端点在上一个的右端点右侧 即存在非盲区 most = max(most, (block[p].x1>lx2 ? lx2 : block[p].x1) - (right > lx1 ? right : lx1));//算出非盲区的长度 两个?:算符使得非盲区不得超出路的范围 right = max(right, block[p].x2);//最后更新一下大盲区右端点位置 } if (signal(most) == 1) printf("%.2lf\n", most);//output else printf("No View\n");//output}int main(void){ //freopen("vs_cin.txt", "r", stdin); //freopen("vs_cout.txt", "w", stdout); while (~scanf("%lf%lf%lf", &hx1, &hx2, &hy) && (signal(hx1) || signal(hx2) || signal(hy))) {//input//没办法 题目说非得3个0才能停下来 scanf("%lf%lf%lf", &lx1, &lx2, &ly);//input scanf("%d", &N);//input fun(); }}
EOF
- POJ 2074
- poj 2074
- poj 2074
- poj 2074
- POJ 2074 视线问题
- POJ 2074 直线相交
- POJ
- poj
- POJ
- POJ
- poj
- poj
- POJ
- POJ
- poj
- POJ
- POJ
- POJ
- java学习之TCP客户端程序
- foreach (int i in d.Values) Console.Write(i);
- KMP算法
- 网站建设和网站运营的关系
- 遇到个奇怪的问题,同时开启本地和远程两个事务,远程事务是sql2000没问题,是sql2008的不报错,但是写不上数据
- poj 2074
- SpringMVC验证
- RX操作符之Observable的创建方式二(defer、range、interval、timer、Empty、Never、Throw)
- 房贷计算器java版
- Mongodb主从复制
- 需求变更的控制及管理
- 让RecyclerView更通用
- 在头文件中加入#program once
- JAVA之TCP网络程序