题目: 传送门

题意:在一个左小角坐标为(0, 0),右上角坐标为(10, 10)的房间里,有 n 堵墙,每堵墙都有两个门。每堵墙的输入方式为 x, y1, y2, y3, y4,x 是墙的横坐标,第一个门的区间为[ (x, y1) ~ (x, y2) ],问你从 (0, 5) 走到 (10, 5) 的最短路径是多少。

0 <= n <= 18

题解:讲每个门的端点存起来,然后,加上(0, 5) 和 (10, 5) 这两个点,暴力判断这些点两两间是否能互相直达,然后再跑一遍最短路就行了。

      你不能直接从 (0, 5) 到 (10, 5) 那你肯定是经过一些门的端点再到终点是最优的。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>
#define LL long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF 1e20
#define inf LLONG_MAX
#define PI acos(-1)
using namespace std; const int N = 1e2 + ;
const double eps = 1e-; struct Point {
double x, y;
Point(double x = , double y = ) : x(x), y(y) { } /// 构造函数
}; /// 向量加减乘除
inline Point operator + (const Point& A, const Point& B) { return Point(A.x + B.x, A.y + B.y); }
inline Point operator - (const Point& A, const Point& B) { return Point(A.x - B.x, A.y - B.y); }
inline Point operator * (const Point& A, const double& p) { return Point(A.x * p, A.y * p); }
inline Point operator / (const Point& A, const double& p) { return Point(A.x / p, A.y / p); } inline int dcmp(const double& x) { if(fabs(x) < eps) return ; else return x < ? - : ; } inline double Cross(const Point& A, const Point& B) { return A.x * B.y - A.y * B.x; } /// 叉积
inline double Dot(const Point& A, const Point& B) { return A.x * B.x + A.y * B.y; } /// 点积
inline double Length(const Point& A) { return sqrt(Dot(A, A)); } /// 向量长度
inline double Angle(const Point& A, const Point& B) { return acos(Dot(A, B) / Length(A) / Length(B)); } /// 向量A,B夹角 inline Point GetLineIntersection(const Point P, const Point v, const Point Q, const Point w) {///求直线p + v*t 和 Q + w*t 的交点,需确保有交点,v和w是方向向量
Point u = P - Q;
double t = Cross(w, u) / Cross(v, w);
return P + v * t;
} inline bool Onsegment(Point p, Point a1, Point a2) { /// 判断点p是否在线段p1p2上
return dcmp(Cross(a1 - p, a2 - p)) == && dcmp(Dot(a1 - p, a2 - p)) <= ;
} inline bool SegmentProperInsection(Point a1, Point a2, Point b1, Point b2) { /// 判断线段是否相交
if(dcmp(Cross(a1 - a2, b1 - b2)) == ) /// 两线段平行
return Onsegment(b1, a1, a2) || Onsegment(b2, a1, a2) || Onsegment(a1, b1, b2) || Onsegment(a2, b1, b2);
Point tmp = GetLineIntersection(a1, a2 - a1, b1, b2 - b1);
return Onsegment(tmp, a1, a2) && Onsegment(tmp, b1, b2);
} Point P[N];
double dis[N][N];
int main() {
int n;
double x, y1, y2, y3, y4;
while(scanf("%d", &n) && n != -) { int cnt = ;
rep(i, , n) {
scanf("%lf %lf %lf %lf %lf", &x, &y1, &y2, &y3, &y4);
P[++cnt] = Point(x, y1);
P[++cnt] = Point(x, y2);
P[++cnt] = Point(x, y3);
P[++cnt] = Point(x, y4);
} rep(i, , cnt + ) rep(j, , cnt + ) if(i == j) dis[i][j] = ; else dis[i][j] = INF; rep(i, , cnt) { /// 判断(0,5)是否能直达P[i],P[i]是否能直达(10,5)
bool flag = ;
int up = ((i + ) / ) * + ;
up -= ;
for(int j = ; j < up; j += ) { /// (0,5)是否能直达P[i]
if(SegmentProperInsection(P[j], P[j + ], Point(, ), P[i]) == false && SegmentProperInsection(P[j + ], P[j + ], Point(, ), P[i]) == false) flag = ;
}
if(!flag) dis[][i] = dis[i][] = Length(Point(, ) - P[i]); flag = ;
for(int j = up + ; j <= cnt; j += ) { /// P[i] 是否能直达(10,5)
if(SegmentProperInsection(P[j], P[j + ], Point(, ), P[i]) == false && SegmentProperInsection(P[j + ], P[j + ], Point(, ), P[i]) == false) flag = ;
}
if(!flag) dis[cnt + ][i] = dis[i][cnt + ] = Length(Point(, ) - P[i]);
} rep(i, , cnt) rep(j, i + , cnt) { /// 枚举两点,判断这两点是否能直达
int st = ((i + ) / ) * + ;
int ed = ((j + ) / ) * ;
bool flag = ;
for(int k = st; k <= ed; k += ) {
if(SegmentProperInsection(P[k], P[k + ], P[i], P[j]) == false && SegmentProperInsection(P[k + ], P[k + ], P[i], P[j]) == false) flag = ;
}
if(!flag) dis[i][j] = dis[j][i] = Length(P[i] - P[j]);
} bool flag = ;
for(int i = ; i <= cnt; i += ) /// 判断(0,5)是否能直达(10,5)
if(SegmentProperInsection(P[i], P[i + ], Point(, ), Point(, )) == false && SegmentProperInsection(P[i + ], P[i + ], Point(, ), Point(, )) == false) flag = ;
if(!flag) dis[][cnt + ] = dis[cnt + ][] = ; rep(k, , cnt + ) rep(i, , cnt + ) rep(j, , cnt + )
if(dis[i][k] + dis[k][j] < dis[i][j]) dis[i][j] = dis[i][k] + dis[k][j];
printf("%.2f\n", dis[][cnt + ]);
}
return ;
}

最新文章

  1. KMP算法实现
  2. Sharepoint学习笔记—习题系列--70-576习题解析 -(Q144-Q146)
  3. NetworkComms V3 模拟登陆
  4. 关于javascript中闭包的理解
  5. HomeKit 与老旧设备
  6. 使用dom4j解析XML文档
  7. Python list方法总结
  8. CvMat 矩阵的使用方法和简单程序
  9. Echarts ecomfe 触摸屏 touch 在IE10下无法显示悬浮框
  10. poj1470 LCA Tarjan
  11. myeclipse中的js文件报错
  12. jQuery加载外部文件的方式get、post、ajax、load的区别及异步加载的实现
  13. C++多态性——函数的覆盖和隐藏
  14. MySQL在ROW模式下通过binlog提取SQL语句
  15. PHP学习笔记 - 进阶篇(4)
  16. 用javascript把扑克牌理理顺!
  17. 50、matplotlib画图示例
  18. 将Session放入Redis
  19. css 把图片变为为黑白
  20. layer弹层基本参数初尝试

热门文章

  1. HDU-6214 Smallest Minimum Cut(最少边最小割)
  2. Git详解之初次运行
  3. Docker底层架构之联合文件系统
  4. 运行MapReduce任务
  5. maven 打包详解
  6. Android教程2020 - RecyclerView获取滑动距离
  7. 【大白话系列】MySQL 学习总结 之 初步了解 InnoDB 存储引擎的架构设计
  8. (5千字)由浅入深讲解动态规划(JS版)-钢条切割,最大公共子序列,最短编辑距离
  9. VC实现快递查询
  10. Codeforces_839