1066 -- Treasure Hunt

  题意是,在一个金字塔中有一个宝藏,金字塔里面有很多的墙,要穿过墙壁才能进入到宝藏所在的地方。可是因为某些原因,只能在两个墙壁的交点连线的中点穿过墙壁。问最少要穿过多少墙壁才能得到宝藏。

  比较容易想到的一个办法就是直接用中点构图,然后判断点与点之间是否能够直接相连,最后bfs得到最小距离。

  我的代码也是这样做,结果相当险的900+ms通过。

代码如下:

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath> using namespace std; const double EPS = 1e-;
const int N = ;
inline int sgn(double x) { return (x > EPS) - (x < -EPS);} struct Point {
double x, y;
Point() {}
Point(double x, double y) : x(x), y(y) {}
bool operator < (Point a) const { return sgn(x - a.x) < || sgn(x - a.x) == && y < a.y;}
bool operator == (Point a) const { return sgn(x - a.x) == && sgn(y - a.y) == ;}
Point operator + (Point a) { return Point(x + a.x, y + a.y);}
Point operator - (Point a) { return Point(x - a.x, y - a.y);}
Point operator * (double p) { return Point(x * p, y * p);}
Point operator / (double p) { return Point(x / p, y / p);}
} ;
inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
inline double veclen(Point a) { return sqrt(dot(a, a));}
inline Point vecunit(Point x) { return x / veclen(x);}
inline Point normal(Point x) { return Point(-x.y, x.x) / veclen(x);}
inline bool onseg(Point x, Point a, Point b) { return sgn(cross(a - x, b - x)) == && sgn(dot(a - x, b - x)) <= ;} struct Line {
Point s, t;
Line() {}
Line(Point s, Point t) : s(s), t(t) {}
Point vec() { return t - s;}
Point point(double p) { return s + vec() * p;}
} ;
inline bool onseg(Point x, Line l) { return onseg(x, l.s, l.t);}
inline Point llint(Line a, Line b) { return a.point(cross(b.vec(), a.s - b.s) / cross(a.vec(), b.vec()));} Point ips[N][N], trs, vex[N * N];
bool out[N * N];
int ipcnt[N], vexcnt;
Line ls[N]; void input(int &n) {
Point tmp[];
for (int i = ; i < n; i++) {
for (int j = ; j < ; j++) cin >> tmp[j].x >> tmp[j].y;
ls[i] = Line(tmp[], tmp[]);
}
ls[n++] = Line(Point(0.0, 0.0), Point(100.0, 0.0));
ls[n++] = Line(Point(100.0, 0.0), Point(100.0, 100.0));
ls[n++] = Line(Point(100.0, 100.0), Point(0.0, 100.0));
ls[n++] = Line(Point(0.0, 100.0), Point(0.0, 0.0));
cin >> trs.x >> trs.y;
} inline Point mid(Point a, Point b) { return (a + b) / 2.0;} int makevex(int n) {
Point tmp;
memset(ipcnt, , sizeof(ipcnt));
for (int i = ; i < n; i++) {
for (int j = ; j < i; j++) {
if (sgn(cross(ls[i].vec(), ls[j].vec()))) {
tmp = llint(ls[i], ls[j]);
if (onseg(tmp, ls[i])) ips[i][ipcnt[i]++] = tmp;
if (onseg(tmp, ls[j])) ips[j][ipcnt[j]++] = tmp;
}
}
}
vexcnt = ;
vex[vexcnt++] = trs;
memset(out, , sizeof(out));
for (int i = ; i < n; i++) {
ips[i][ipcnt[i]++] = ls[i].s;
ips[i][ipcnt[i]++] = ls[i].t;
sort(ips[i], ips[i] + ipcnt[i]);
for (int j = ; j < ipcnt[i]; j++) {
if (ips[i][j - ] == ips[i][j]) continue;
vex[vexcnt++] = mid(ips[i][j - ], ips[i][j]);
}
}
// cout << vexcnt << endl;
for (int i = ; i < vexcnt; i++) {
for (int j = n - ; j < n; j++) {
if (onseg(vex[i], ls[j])) {
out[i] = true;
break;
}
}
}
// for (int i = 0; i < vexcnt; i++) cout << out[i]; cout << endl;
return vexcnt;
} inline bool ssint(Line a, Line b) { return sgn(cross(a.s - b.s, a.t - b.s)) * sgn(cross(a.s - b.t, a.t - b.t)) <
&& sgn(cross(b.s - a.s, b.t - a.s)) * sgn(cross(b.s - a.t, b.t - a.t)) < ;} bool mat[N * N][N * N]; bool test(int i, int j, int n) {
Line tmp = Line(vex[i], vex[j]);
for (int a = ; a < n; a++)
if (onseg(vex[i], ls[a]) && onseg(vex[j], ls[a])) return false;
for (int a = ; a < n; a++)
if (ssint(tmp, ls[a])) return false;
return true;
} void makemat(int n, int m) {
memset(mat, , sizeof(mat));
for (int i = ; i < n; i++) {
for (int j = ; j < i; j++) {
if (test(i, j, m)) mat[i][j] = mat[j][i] = true;
}
}
// for (int i = 0; i < n; i++) {
// for (int j = 0; j < n; j++) cout << mat[i][j]; cout << endl;
// }
} int q[N * N * N];
bool vis[N * N]; int bfs(int n) {
int qh, qt;
memset(vis, , sizeof(vis));
qh = qt = ;
q[qt++] = ;
vis[] = true;
int cnt = ;
while (qh < qt) {
int sz = qt - qh;
cnt++;
for (int i = ; i < sz; i++) {
int cur = q[qh++];
// cout << cur << endl;
// cout << vex[cur].x << ' ' << vex[cur].y << endl;
for (int j = ; j < n; j++) {
if (vis[j] || !mat[cur][j]) continue;
q[qt++] = j;
vis[j] = true;
if (out[j]) return cnt;
}
}
}
return -;
} int main() {
// freopen("in", "r", stdin);
int n;
while (cin >> n) {
input(n);
int m;
makemat(m = makevex(n), n);
cout << "Number of doors = " << bfs(m) << endl;
}
return ;
}

——written by Lyon

poj 1066 Treasure Hunt (Geometry + BFS)的更多相关文章

  1. POJ 1066 Treasure Hunt(线段相交判断)

    Treasure Hunt Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4797   Accepted: 1998 Des ...

  2. POJ 1066 Treasure Hunt(相交线段&amp;&amp;更改)

    Treasure Hunt 大意:在一个矩形区域内.有n条线段,线段的端点是在矩形边上的,有一个特殊点,问从这个点到矩形边的最少经过的线段条数最少的书目,穿越仅仅能在中点穿越. 思路:须要巧妙的转换一 ...

  3. POJ 1066 - Treasure Hunt - [枚举+判断线段相交]

    题目链接:http://poj.org/problem?id=1066 Time Limit: 1000MS Memory Limit: 10000K Description Archeologist ...

  4. poj 1066 Treasure Hunt

    http://poj.org/problem?id=1066 #include <cstdio> #include <cstring> #include <cmath&g ...

  5. POJ 1066 Treasure Hunt [想法题]

    题目链接: http://poj.org/problem?id=1066 --------------------------------------------------------------- ...

  6. POJ 1066 Treasure Hunt (线段相交)

    题意:给你一个100*100的正方形,再给你n条线(墙),保证线段一定在正方形内且端点在正方形边界(外墙),最后给你一个正方形内的点(保证不再墙上) 告诉你墙之间(包括外墙)围成了一些小房间,在小房间 ...

  7. POJ 1066 Treasure Hunt【线段相交】

    思路:枚举四边墙的门的中点,与终点连成一条线段,判断与其相交的线段的个数.最小的加一即为答案. 我是傻逼,一个数组越界调了两个小时. #include<stdio.h> #include& ...

  8. POJ 1066 Treasure Hunt --几何,线段相交

    题意: 正方形的房子,给一些墙,墙在区域内是封闭的,给你人的坐标,每穿过一道墙需要一把钥匙,问走出正方形需要多少把钥匙. 解法: 因为墙是封闭的,所以绕路也不会减少通过的墙的个数,还不如不绕路走直线, ...

  9. 简单几何(线段相交) POJ 1066 Treasure Hunt

    题目传送门 题意:从四面任意点出发,有若干障碍门,问最少要轰掉几扇门才能到达终点 分析:枚举入口点,也就是线段的两个端点,然后选取与其他线段相交点数最少的 + 1就是答案.特判一下n == 0的时候 ...

随机推荐

  1. [翻译] MaxMind DB 文件格式规范

    MaxMind DB 文件格式规范来源:http://maxmind.github.io/MaxMind-DB/翻译:御风(TX:965551582)2017-03-23 -------------- ...

  2. 洛谷P1970 [NOIP2013提高组Day2T2] 花匠

    P1970 花匠 题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定 把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希 望剩下的花排 ...

  3. 【洛谷P1827】【USACO】 美国血统 American Heritage 由二叉树两个序列求第三个序列

    P1827 美国血统 American Heritage 题目描述 农夫约翰非常认真地对待他的奶牛们的血统.然而他不是一个真正优秀的记帐员.他把他的奶牛 们的家谱作成二叉树,并且把二叉树以更线性的&q ...

  4. 【python爬虫】加密代理IP的使用与设置一套session请求头

    1:代理ip请求,存于redis: # 请求ip代理连接,更新redis的代理ip def proxy_redis(): sr = redis.Redis(connection_pool=Pool) ...

  5. Keil新建工程步骤

    第一步:创建工程文件夹 1.新建一个文件夹,例如: 2.在文件夹下创建子文件夹: 文件夹说明: App:存放硬件控制程序: Libraries:存放固件库: Obj:存放生成的文件: Public:存 ...

  6. vue 根据数组中某一项的值进行排序

    一.前言 我在vue项目中遇到了一个表格排序的需求,根据某一项的值的大小从大到小调整数组顺序. 二.代码 表格大概是这个样子,样式和图片在代码中简化了. <table class="r ...

  7. LintCode刷题笔记-- O(1) Check Power of 2

    标签: 位运算 题目: Using O(1) time to check whether an integer n is a power of 2. 解题思路: 这道题是利用位运算判断一个数是不是2 ...

  8. GeoServer手动发布本地Shapefile地图

    首先,本文实现的结果图给大家展现一下: 放大的样子: 颜色是通过属性中某个字段值来分级的,可以自定义. 上面功能是用ArcGIS切片好数据,在Geoserver 中发布,并用google地图作为底图展 ...

  9. Servlet容器container

    通俗点说,所谓容器,就是放东西的地方.Servlet容器自然就是放Servlet的地方.J2EE开发,是有分工的.一般的程序员,写得都是应用开发,我们会按照一定的规则,开发我们的系统,比如用Servl ...

  10. TZOJ4777: 方格取数

    4777: 方格取数  Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByteTotal Submit: 11       ...