题目链接: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; }