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. java-多线程安全-锁

    一 同步函数 1.1 一般的方法 同步的另一种体现形式:同步函数. 同步函数使用的锁是哪个?经过分析:大概猜的是this,因为函数必须被对象调用. 验证:写一个同步代码块,写一个同步函数,如果同步代码 ...

  2. HDU 3555 (递推&&记忆化)

    #include<stdio.h> #include<string.h> #define max 25 typedef __int64 LL; LL dp[max][]; // ...

  3. WPF DrawingVisual详解

    在WPF中,如果需要绘制大量图形元素,并且对性能要求严苛的话,最好使用DrawingVisual,当然,你也可以选用 Path类和比Path类更轻量级的Geometry(几何形状)来实现你的需求,但是 ...

  4. 【python小随笔】celery周期任务(简单原理)

    1:目录结构 |--celery_task |--celery.py # 执行任务的main函数 |--task_one # 第一个任务 |--task_two # 第2个任务 . . . . |-- ...

  5. IDEA:将WEB-INF\lib下的Jar包添加到项目中

    打开Project Structure[可以使用快捷键:Ctrl+Alt+Shift+S] 左侧选中Modules,在Dependecies中,点击右侧"+"号,选择JARS or ...

  6. Directx11教程(46) alpha blend(3)

    原文:Directx11教程(46) alpha blend(3)       现在我们尝试改变box的贴图,使用一张带alpha的dds文件wirefence.dds, 用directx textu ...

  7. KiCad EDA 如何修改 Pcbnew 线路板的背景色?

    KiCad EDA 如何修改 Pcbnew 线路板的背景色? 关于背景色,传统的原理图是白色,线路板是黑色. EDA 软件 类型 颜色 Protel 原理图 浅黄色 Protel PCB 黑色 Orc ...

  8. oralce触发器

    n  触发器的分类 DML(insert,delete,update)触发器 DDL(create table ,create view...drop...)触发器 系统触发器(与系统相关的触发器,比 ...

  9. Linux常用命令1 文件处理命令

    1.命令格式 1.用中括号括起来的内容都不是必填内容,碧如上图的选项和参数,有些命令不写选项和参数也可以执行 2.注意图中的简化选项与完整选项说明,完整选项要两个横杆-- 2.目录处理命令ls 1.文 ...

  10. (五)IO流之ByteArrayInput/OutputStream

    ByteArrayInputStream:是把字节数组当成源的输入流 String string="hello shanghai"; ByteArrayInputStream bi ...