POJ 1556

来源:互联网 发布:如何判定网络是否稳定 编辑:程序博客网 时间:2024/06/06 01:56

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

————————————————————————————————————————————————————

题目简述:如图中所示,已知起点和终点,中间有墙挡住,问最短的路是多长

————————————————————————————————————————————————————

解题思路:看别人的解题报告是用图+dijkstra做的。我没有用图论的方法,直接做的。

我的思路是,读入各点,按顺序存进p数组(p是个结构体,其中用了重载),因为每个x坐标就对应着4个点,所以不需要做标记,有寻址公式就行。

然后将x的坐标按顺序存到xs数组中。然后开始对各个点,按顺序扫描,如果和起点之间无障碍物,则该点的len就是到起点的距离。如果有障碍物,就

从p[0]点开始一个一个的扫描,如果与p[j]点之间没有障碍物,则计算出到该点距离加上该点的len。想法是很裸的(这个词刚刚学会),而且话说其实

应该把起点也放入p 数组中,这样不需要分情况讨论了,代码会更加简洁,不修改了。

其中对于障碍物的判断方法,我是这样做的: 如果我们当前状态是i,待检测的点是j,我们可以用点斜式列出过点i和点j的方程。将i和j之间的墙们的横坐标带进

方程(xs就用上了,再加上一个寻址公式),求出一个纵坐标,再考查纵坐标是否在墙上,就可以了。思路挺简单,不过写起来有点麻烦,寻址公式要特别小心。

————————————————————————————————————————————————————

题目小结:

一开始没有ac,遇到的问题多由粗心所致:

1、bst求出来之后,忘记赋值给p[i].len  ( = = 这么傻的问题都能犯啊)。。。。

2、寻址公式写错了个地方。

另外,在写重载的时候,一开始没有编译通过,问题如下:

3、重载时重载函数要与结构体名一致。

————————————————————————————————————————————————————

待解问题:

1、重载时需要加入一行     Line(){};

     否则会报错 |error: no matching function for call to 'Line::Line()'|,不知为何

2、由于符号重载时多加了个 &,故报warning: reference to local variable 'c' returned|

下学期就该学c++,大概到时候就明白了吧,先搁着!

————————————————————————————————————————————————————

源代码,其中判断相交的函数没用上,算作下次的模板。

#include<cstdio>#include<cstring>#include<algorithm>#include<math.h>using namespace std;typedef float T;struct Pt{   T x;   T y;   T len;   Pt(){}   Pt(T px,T py)   {       x = px;       y = py;   }   Pt &operator +(const Pt &p) const   {       Pt c;       c.x = x + p.x;       c.y = y + p.y;       return c;   }   Pt &operator -(const Pt &p) const   {       Pt c;       c.x = x - p.x;       c.y = y - p.y;       return c;   }};struct Line{    Pt a;    Pt b;    int cont;    Line(){}    Line (Pt p1,Pt p2)    {       a = p1;       b = p2;    }}line[1010];T dpr(Pt a,Pt b,Pt c)     //µã»ý{    return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y);}T cpr(Pt a,Pt b,Pt c)        //ab * ac{    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);}bool cmp(Line l1,Line l2){    return l1.a.x < l2.a.x;}T min(T a,T b){    if(a>b) return b;    else   return a;}bool segments_intersect(Pt p1,Pt p2,Pt p3,Pt p4)        //严格相交,即交在端点不算相交,不需要判断交点位置,相交时返回1。本题亦不会出现点在线段上的问题{    float d1,d2,d3,d4;    d1 = cpr(p1,p3,p4);    d2 = cpr(p2,p3,p4);    d3 = cpr(p3,p1,p2);    d4 = cpr(p4,p1,p2);    if(d1*d2<0 && d3*d4<0)      return 1;    else      return 0;}Pt p[100],p0,pn;int k = 0,m = 0;float xs[100];bool segments(Pt a,Pt b,int i,int j)         //求与各个x的交点{    int k = 0,t = 0;    T y = 0;    for(k = i/4+1;k<j/4+1;k++)    {       y = a.y + (b.y - a.y)*(xs[k] - a.x)/(b.x-a.x);       if(y < p[(k-1)*4].y || (y<p[(k-1)*4+2].y && y>p[(k-1)*4+1].y) || y>p[(4*k-1)].y )         return 1;    }    return 0;}T d(Pt a,Pt b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}int main(){    int n = 0,i = 0,j = 0;    T x = 0,y = 0;    float bst = 0;    unsigned temp = 0;    p0 = Pt(0,5);    pn = Pt(10,5);    while((scanf("%d",&n),n)!=-1)    {       k = 0;       m = 1;       xs[0] = 0;       for(i = 0;i<n;i++)       {          scanf("%f",&x);          xs[m++] = x;          for(j = 0;j<4;j++)          {              scanf("%f",&y);              p[k++] = Pt(x,y);          }       }      if(!segments(p0,pn,0,k))      {          pn.len = d(pn,p0);          printf("%.2f\n",pn.len);          continue;      }       for(i = 0;i<k;i++)       {          bst = (~temp)>>1;          if(i/4 == 0)            p[i].len = d(p[i],p0);          else          {              if(!segments(p[i],p0,0,i))              {                p[i].len = d(p[i],p0);                continue;              }              for(j = 0;j<=(i/4)*4-1;j++)              {                 if(!segments(p[i],p[j],j,i))                   if(d(p[i],p[j])+p[j].len<bst)                     bst = d(p[i],p[j])+p[j].len;              }              p[i].len = bst;          }       }       bst = (~temp)>>1;       for(i = 0;i<k;i++)       {           if(!segments(p[i],pn,i,k))             if(d(p[i],pn)+p[i].len<bst)                bst = d(p[i],pn)+p[i].len;       }       printf("%.2f\n",bst);    }    return 0;}