poj1066
很好的一道题。题意是,一个正方形围墙内有一些交错的内墙,内墙的端点都在正方形上,在正方形内部有一个点,求从正方形外到这个点的最少要走的门数,门只能是线段的中点。
思路很巧妙,因为从一个点到终点不可能“绕过”围墙,只能传过去,所以门是否开在中点是无所谓的,只要求四周线段中点到终点的线段与墙的最少交点个数即可。更进一步,实际上,只需判断四周围墙的所有点与终点的连线与内墙的最少交点加一即可。
请看下图的红色线,与蓝色线交点,即是上述的交点。
#include <iostream>
#include <math.h> #define eps 1e-8
#define zero(x) (((x)>0?(x):-(x))<eps) #define pi acos(-1.0) struct point
{
double x, y;
}; struct line
{
point a, b;
}; //计算cross product (P1-P0)x(P2-P0)
double xmult(point p1, point p2, point p0)
{
return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y);
}
//计算dot product (P1-P0).(P2-P0)
double dmult(point p1, point p2, point p0)
{
return (p1.x - p0.x)*(p2.x - p0.x) + (p1.y - p0.y)*(p2.y - p0.y);
} //两点距离
double distance(point p1, point p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
} //判三点共线
bool dots_inline(point p1, point p2, point p3)
{
return zero(xmult(p1, p2, p3));
} //判点是否在线段上,包括端点
bool dot_online_in(point p, line l)
{
return zero(xmult(p, l.a, l.b)) && (l.a.x - p.x)*(l.b.x - p.x) < eps && (l.a.y - p.y)*(l.b.y - p.y) < eps;
} //判点是否在线段上,不包括端点
bool dot_online_ex(point p, line l)
{
return dot_online_in(p, l) && (!zero(p.x - l.a.x) || !zero(p.y - l.a.y)) && (!zero(p.x - l.b.x) || !zero(p.y - l.b.y));
} //判两点在线段同侧,点在线段上返回0
bool same_side(point p1, point p2, line l)
{
return xmult(l.a, p1, l.b)*xmult(l.a, p2, l.b) > eps;
} //判两点在线段异侧,点在线段上返回0
bool opposite_side(point p1, point p2, line l)
{
return xmult(l.a, p1, l.b)*xmult(l.a, p2, l.b) < -eps;
} //判两线段相交,包括端点和部分重合
bool intersect_in(line u, line v)
{
if (!dots_inline(u.a, u.b, v.a) || !dots_inline(u.a, u.b, v.b))
return !same_side(u.a, u.b, v) && !same_side(v.a, v.b, u);
return dot_online_in(u.a, v) || dot_online_in(u.b, v) || dot_online_in(v.a, u) || dot_online_in(v.b, u);
} //判两线段相交,不包括端点和部分重合
bool intersect_ex(line u, line v)
{
return opposite_side(u.a, u.b, v) && opposite_side(v.a, v.b, u);
} int main()
{
point p[100];
line wall[35], link[100];
int n;
while (std::cin >> n)
{
int j = 0;
for (int i = 0; i < n << 1; i++)//边界点
{
std::cin >> p[i].x >> p[i].y;
}
for (int i = 0; i < n << 1; i++)//构造墙
{
wall[j].a = p[i];
wall[j++].b = p[++i];
}
double x, y;
std::cin >> x >> y;
int k = 0;
for (int i = 0; i < n << 1; i++)//构造宝藏点到边界所有点的连线
{
link[k].a = p[i];
link[k].b.x = x, link[k++].b.y = y;
} //for (int i = 0; i < n; i++)
//{
// std::cout << wall[i].a.x << ' ' << wall[i].a.y << ' ' << wall[i].b.x << ' ' << wall[i].b.y << std::endl;
//} //for (int i = 0; i < n << 1; i++)
//{
// std::cout << link[i].a.x << ' ' << link[i].a.y << ' ' << link[i].b.x << ' ' << link[i].b.y << std::endl;
//} int min = 100000;
for (int i = 0; i < n << 1; i++)
{
int count = 0;
for (int j = 0; j < n; j++)
{
if (intersect_ex(link[i], wall[j]))
{
count++;
/*std::cout << link[i].a.x << '%' << link[i].a.y << '%' << link[i].b.x << '%' << link[i].b.y << std::endl;
std::cout << wall[j].a.x << '%' << wall[j].a.y << '%' << wall[j].b.x << '%' << wall[j].b.y << std::endl << std::endl;*/
}
}
//std::cout << count << std::endl;
if (count < min) min = count;
}
if (n == 0) std::cout << "Number of doors = 1" << std::endl;
else std::cout <<"Number of doors = "<< min + 1<< std::endl;
}
}
poj1066的更多相关文章
- poj1066 Jugs
poj1066 Jugs http://poj.org/problem?id=1606 解题思路:本题可以用数学方法解得,最易理解,常规的解法是搜索.直接用接近模拟的广度优先搜索即可过. 给两个容器, ...
- POJ1066线段交点
POJ1066 题意:给出一个100*100的正方形区域,通过若干连接区域边界的线段将正方形区域分割为多个不规则多边形小区域,然后给出宝藏位置,要求从区域外部开辟到宝藏所在位置的一条路径,使得开辟路径 ...
- poj1066(叉乘的简单应用)
做完了才发现,好像没有人和我的做法一样的,不过我怎么都觉得我的做法还是挺容易想的. 我的做法是: 把周围的方框按顺时针编号,然后对于每一条边,如果点出现在边的一侧,则把另一侧所有的点加1,这样最后统计 ...
- 算法:poj1066 宝藏猎人问题。
package practice; import java.util.Scanner; public class TreasureHunt { public static void main(Stri ...
- poj1066 Treasure Hunt【计算几何】
Treasure Hunt Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 8192 Accepted: 3376 Des ...
- 几何+线段交点+spfa(POJ1066)
Treasure Hunt Time Limit : 2000/1000ms (Java/Other) Memory Limit : 20000/10000K (Java/Other) Total ...
- POJ1066 Treasure Hunt
嘟嘟嘟 题意看题中的图就行:问你从给定的点出发最少需要穿过几条线段才能从正方形中出去(边界也算). 因为\(n\)很小,可以考虑比较暴力的做法.枚举在边界中的哪一个点离开的.也就是枚举四周的点\((x ...
- POJ1066:Treasure Hunt——题解
http://poj.org/problem?id=1066 题目大意:给一个由墙围成的正方形,里面有若干墙,每次破墙只能从(当前看到的)墙的中点破,求最少破多少墙才能看到宝藏. —————————— ...
- poj1066 线段相交简单应用(解题报告)
#include<stdio.h> #include<math.h> const double eps=1e-8; int n; struct Point { double x ...
随机推荐
- #Leet Code# LRU Cache
语言:C++ 描述:使用单链表实现,HeadNode是key=-1,value=-1,next=NULL的结点.距离HeadNode近的结点是使用频度最小的Node. struct Node { in ...
- QFTP走了以后QNetworkAccessManager出现了
QNetworkAccessManager Class Header: #include <QNetworkAccessManager>qmake: QT += networ ...
- python 包导入规则
python 包导入规则,恶心了一天,终于搞清楚了 1.目录 speed data __init__.py __init__.py static templates view __init__.py ...
- PS证件照换背景
综述 博主原创内容. 在PS里,对于抠图,比较有技术含量的便是抠头发丝了,下面为大家带来一个比较详细的抠头发丝的教程. 素材准备 在这里我们用这张图片作为抠图素材,下面让我们一步步来演示抠图的过程,并 ...
- JDK源码阅读(三) Collection<T>接口,Iterable<T>接口
package java.util; public interface Collection<E> extends Iterable<E> { //返回该集合中元素的数量 in ...
- [BZOJ 2127] happiness 【最小割】
题目链接:BZOJ - 2127 题目分析 首先,每个人要么学文科,要么学理科,所以可以想到是一个最小割模型. 我们就确定一个人如果和 S 相连就是学文,如果和 T 相连就是学理. 那么我们再来确定建 ...
- 用POLL的方式,没有跑出结果来,立此存照
咦,这些内容,和我以前看内核时的东东,对应起来了.. SELECT,POLL,EPOLL,非阻塞,异步之类的... 但我没有调出来.回家有空了可以看看,不用再敲打代码啦... #!/usr/bin/e ...
- Bitmap介绍
转自:http://blog.csdn.net/xgdofull/article/details/5424611 简单的说就是用数组存放若有数据就标志为1或true,若不存在标志为0或false.比如 ...
- 【响应式Web设计实践 #BOOK#】
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- ant 学习与开发
ant 学习与开发 http://www.blogjava.net/amigoxie/archive/2007/11/09/159413.html