zoukankan      html  css  js  c++  java
  • poj 1556 线段相交加最短路

    题意:在平面直角坐标系上有一个10*10的正方形房间,房间中有n堵平行y方向的墙,每堵墙上有两扇门,

    问从房间最左边的(0,5)处,通过门,到达房间最右边的(10,5)处的最短距离

    题解:考虑从起始点,若沿x轴走则可以一直走到被墙堵住为止,此时其需要走到堵住它的墙的门的端点,一定可以转化成更早就从某一个门的端点开始走距离更短,可以考虑成两点AB之间,不能直接用线段相连,那么是一直走平行于X轴的直线然后转折到另一个点,还是直接走更趋近于AB的斜线然后转折,明显后一种距离更短。

    把起点和终点和门上所有端点设想为图上的点,每两个点之间建边,如果两点之间会被墙阻隔则设为无穷大,因为数据很小,可以随便遍历,不用太考虑时间复杂度

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <vector>
      4 #include <algorithm>
      5 #include <iostream>
      6 #include <map>
      7 #include <queue>
      8 #include <stack>
      9 #include <cmath>
     10 //#pragma comment(linker, "/STACK:102400000,102400000")
     11 using namespace std;
     12 #define PF(x) cout << "debug: " << x << " ";
     13 #define EL cout << endl;
     14 #define PC(x) puts(x);
     15 typedef long long ll;
     16 #define CLR(x, v) sizeof (x, v, sizeof(x))
     17 using namespace std;
     18 const int INF = 0x5f5f5f5f;
     19 const int  N= 2e5 + 10;
     20 const int mod=1e9 + 7;
     21 const int maxn = 100;
     22 const double eps = 1e-8;
     23 const double PI = acos(-1.0);
     24 int t;
     25 int sgn(double x){
     26     if(fabs(x) < eps) return 0;
     27     if(x < 0) return -1;
     28     else return 1;
     29 
     30 }
     31 struct Point{
     32     double x,y;
     33     Point() { }
     34     Point(double _x,double _y){
     35         x = _x,y = _y;
     36     }
     37     Point operator - (const Point &b) const{ //相对坐标
     38         return Point(x - b.x,y - b.y);
     39     }
     40     double operator ^(const Point &b)const{//叉积
     41         return x*b.y - y*b.x;
     42     }
     43     double operator *(const Point &b)const{//点积
     44         return x*b.x + y*b.y;
     45     }
     46     void transXY(double B){
     47         double tx = x,ty = y;
     48         x = tx*cos(B) - ty*sin(B);
     49         y = tx*sin(B) + ty*cos(B);
     50     }
     51 };
     52 struct Line{
     53     Point s,e;
     54     Line() { }
     55     Line (Point _s,Point _e){
     56         s = _s,e = _e;
     57     }
     58     //两直线相交求交点
     59     //第一个值为0表示直线重合,为1表示平行,为2是相交
     60     //只有第一个值为2时交点才有意义
     61     pair<int,Point> operator &(const Line &b) const{
     62         Point res = s;
     63         if(sgn((s-e)^(b.s-b.e)) == 0){
     64             if(sgn((s-b.e)^(b.s-b.e)) == 0)
     65                 return make_pair(0,res);//重合
     66             else
     67                 return make_pair(1,res);
     68         }
     69         double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
     70         res.x += (e.x-s.x)*t;
     71         res.y += (e.y-s.y)*t;
     72         return make_pair(2,res);
     73     }
     74 };
     75 double dist(Point a,Point b){
     76     return sqrt((b-a)*(b-a));
     77 }
     78 bool Seg_inter_line(Line l1,Line l2){//判断直线l1与线段l2是否相交
     79     return sgn((l2.s - l1.e) ^ (l1.s-l1.e)) * sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0;
     80 }
     81 bool inter(Line l1,Line l2){
     82     return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
     83     max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
     84     max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
     85     max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
     86     sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0&&
     87     sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0;
     88 
     89 }
     90 int n,cntl,cntp;
     91 double gra[maxn][maxn];
     92 Line line[maxn];
     93 Point pt[maxn];
     94 void flyod(){
     95     for(int k = 1;k <= cntp;k++)
     96         for(int i = 1;i <= cntp;i++)
     97             for(int j = 1;j <= cntp;j++)
     98                 gra[i][j] = min(gra[i][j],gra[i][k]+gra[k][j]);
     99 
    100 }
    101 bool cek(Line l){
    102     for(int i = 1;i <= cntl;i++){
    103         if(dist(line[i].s,l.s) == 0||dist(line[i].s,l.e) == 0||dist(line[i].e,l.s) == 0||dist(line[i].e,l.e) == 0)
    104         continue;
    105         if(inter(l,line[i]))
    106             return false;
    107     }
    108     return true;
    109 }
    110 int main()
    111 {
    112   // freopen("in.txt","r",stdin);
    113     while(~scanf("%d",&n)){
    114         if(n == -1)
    115             break;
    116         double x,h1,h2,h3,h4;
    117         cntl = 0,cntp = 2;
    118         for(int i = 1;i < 100;i++)
    119             for(int j = 1;j <100;j++)
    120                 gra[i][j] = 10000.0;
    121         pt[1] = Point(0,5);
    122         pt[2] = Point(10,5);
    123         for(int i = 1;i <= n;i++){
    124             scanf("%lf%lf%lf%lf%lf",&x,&h1,&h2,&h3,&h4);
    125             line[++cntl] = Line(Point(x,0),Point(x,h1));
    126             line[++cntl] = Line(Point(x,h2),Point(x,h3));
    127             line[++cntl] = Line(Point(x,h4),Point(x,10));
    128             pt[++cntp] = Point(x,h1);
    129             pt[++cntp] = Point(x,h2);
    130             pt[++cntp] = Point(x,h3);
    131             pt[++cntp] = Point(x,h4);
    132         }
    133         for(int i = 1;i <= cntp;i++)
    134             for(int j = i;j <= cntp;j++){
    135                 if(i == j){
    136                     gra[i][i] = 0;
    137                     continue;
    138                 }
    139                 Line l = Line(pt[i],pt[j]);
    140                 if(cek(l)){
    141                     gra[i][j] = dist(pt[i],pt[j]);
    142                     gra[j][i] = gra[i][j];
    143                 }
    144 
    145             }
    146         flyod();
    147         printf("%.2f
    ",gra[1][2]);
    148     }
    149     return 0;
    150 }
  • 相关阅读:
    常见优化函数
    排序算法
    小米编程题
    leetcode 刷题
    beam_search 和 viterbi算法的区别
    快速排序
    vitrebi算法进行分词的案例
    python 进行视频剪辑
    keras实现MobileNet
    HMM、CTC、RNN-T训练时所有alignment的寻找方法
  • 原文地址:https://www.cnblogs.com/shimu/p/5832729.html
Copyright © 2011-2022 走看看