很好的一道题。题意是,一个正方形围墙内有一些交错的内墙,内墙的端点都在正方形上,在正方形内部有一个点,求从正方形外到这个点的最少要走的门数,门只能是线段的中点。

思路很巧妙,因为从一个点到终点不可能“绕过”围墙,只能传过去,所以门是否开在中点是无所谓的,只要求四周线段中点到终点的线段与墙的最少交点个数即可。更进一步,实际上,只需判断四周围墙的所有点与终点的连线与内墙的最少交点加一即可。

请看下图的红色线,与蓝色线交点,即是上述的交点。


#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的更多相关文章

  1. poj1066 Jugs

    poj1066 Jugs http://poj.org/problem?id=1606 解题思路:本题可以用数学方法解得,最易理解,常规的解法是搜索.直接用接近模拟的广度优先搜索即可过. 给两个容器, ...

  2. POJ1066线段交点

    POJ1066 题意:给出一个100*100的正方形区域,通过若干连接区域边界的线段将正方形区域分割为多个不规则多边形小区域,然后给出宝藏位置,要求从区域外部开辟到宝藏所在位置的一条路径,使得开辟路径 ...

  3. poj1066(叉乘的简单应用)

    做完了才发现,好像没有人和我的做法一样的,不过我怎么都觉得我的做法还是挺容易想的. 我的做法是: 把周围的方框按顺时针编号,然后对于每一条边,如果点出现在边的一侧,则把另一侧所有的点加1,这样最后统计 ...

  4. 算法:poj1066 宝藏猎人问题。

    package practice; import java.util.Scanner; public class TreasureHunt { public static void main(Stri ...

  5. poj1066 Treasure Hunt【计算几何】

    Treasure Hunt Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 8192   Accepted: 3376 Des ...

  6. 几何+线段交点+spfa(POJ1066)

    Treasure Hunt Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 20000/10000K (Java/Other) Total ...

  7. POJ1066 Treasure Hunt

    嘟嘟嘟 题意看题中的图就行:问你从给定的点出发最少需要穿过几条线段才能从正方形中出去(边界也算). 因为\(n\)很小,可以考虑比较暴力的做法.枚举在边界中的哪一个点离开的.也就是枚举四周的点\((x ...

  8. POJ1066:Treasure Hunt——题解

    http://poj.org/problem?id=1066 题目大意:给一个由墙围成的正方形,里面有若干墙,每次破墙只能从(当前看到的)墙的中点破,求最少破多少墙才能看到宝藏. —————————— ...

  9. poj1066 线段相交简单应用(解题报告)

    #include<stdio.h> #include<math.h> const double eps=1e-8; int n; struct Point { double x ...

随机推荐

  1. flash player over linux

    flashplayer官方网址:https://get.adobe.com/cn/flashplayer/ flash插件安装方法一(适用于ubuntu等linux系统):               ...

  2. iOS: 学习笔记, 添加一个带界面约束的控制器

    1. 创建一个空iOS应用程序(Empty Application). 2. 添加加控制器类. 修改控制器类的viewDidLoad - (void)viewDidLoad { [super view ...

  3. DataTable一些操作

    DataTable ReturnDt = new DataTable("Tab_Result"); ReturnDt.Columns.AddRange(new DataColumn ...

  4. http server v0.1_http_server.c

    /**************************************************************** filename: http_server.c author: xx ...

  5. 如何用 React Native 创建一个iOS APP?

    诚然,React Native 结合了 Web 应用和 Native 应用的优势,可以使用 JavaScript 来开发 iOS 和 Android 原生应用.在 JavaScript 中用 Reac ...

  6. Technology Trader

    zoj2071:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2071 题意:题意一些零件,每一个零件会有一个花费,然后用这 ...

  7. quartz定时任务时间配置

    quartz定时任务时间设置描述(2011-03-03 16:23:50)转载▼标签: quartz时间it 分类: 凌乱小记  这些星号由左到右按顺序代表 :     *    *     *    ...

  8. cocosBuilder使用总结

    原创,转载请注明出处! 基本流程 >=-. 准备工作 #. 把一个项目场景相关的,相对独立(别的场景用不到)的碎图,用TexturePack拼接成大的png图片文件及plist数据字处理文件 # ...

  9. Fixing common issues when hosting a .NET 4.0 WCF service in IIS 7

    http://sandrinodimattia.net/fixing-common-issues-when-hosting-a-net-4-0-wcf-service-in-iis-7/ Until ...

  10. 身为java程序员你需要知道的网站(包含书籍,面试题,架构...)

    推荐几本书<高级java程序员值得拥有的10本书>,     首页 所有文章 资讯 Web 架构 基础技术 书籍 教程 我要投稿 更多频道 » - 导航条 - 首页 所有文章 资讯 Web ...