poj1556
2010-10-13 21:17
113 查看
题意:房间里有n堵墙,每面墙上有两扇门,求从房间最左端中点到最右端中点的最短路径
心得:解析很简单,简单的计算几何+简单的最短路径
WA点:计算几何代码量大,很容易出错,这道题让我恶心了好几天╮(╯_╰)╭。首先是模板敲错了好几处,有很水的,像是2敲成-2,也有因为不熟悉的,比如敲晓东的图论模板head数组中存的是点我敲成了边。然后就是存储方式没有选好,晓东的思路跟我一样,每面墙6个点存好,但是他用的是二维数组,我用的是一维模拟二维,结果最后数据对撞的时候发现,错误的原因是模拟的时候寻址公式错了╮(╯_╰)╭少乘以了6。
代码(我的,都不好意思贴了╮(╯_╰)╭):
晓东的代码:
心得:解析很简单,简单的计算几何+简单的最短路径
WA点:计算几何代码量大,很容易出错,这道题让我恶心了好几天╮(╯_╰)╭。首先是模板敲错了好几处,有很水的,像是2敲成-2,也有因为不熟悉的,比如敲晓东的图论模板head数组中存的是点我敲成了边。然后就是存储方式没有选好,晓东的思路跟我一样,每面墙6个点存好,但是他用的是二维数组,我用的是一维模拟二维,结果最后数据对撞的时候发现,错误的原因是模拟的时候寻址公式错了╮(╯_╰)╭少乘以了6。
代码(我的,都不好意思贴了╮(╯_╰)╭):
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <queue> #include <cmath> using namespace std; //图论部分 int e; int head[10000]; int from[10000]; int next[10000]; int pnt[10000]; double cost[10000]; double d[10000]; void Init() { e = 0; memset(head,-1,sizeof(head)); } void AddEdge(int start,int end,double c) { from[e] = start; next[e] = head[start]; pnt[e] = end; cost[e] = c; head[start] = e++; } //Dijkstra bool flag[10000]; struct Cmp { bool operator()(int a,int b) { return d[a] > d[b]; } }; void Dijkstra(int n,int s) { for(int i = 0; i <=n; i++) { d[i] = 10000; } d[s] = 0; memset(flag,0,sizeof(flag)); priority_queue<int,vector<int>,Cmp> q; q.push(s); int s0,t0,h0,next0; double c0; while(!q.empty()) { h0 = q.top(); q.pop(); if(flag[h0]) continue; flag[h0] = true; next0 = head[h0]; while(next0!=-1) { s0 = from[next0]; t0 = pnt[next0]; c0 = cost[next0]; if(d[t0]>d[s0]+c0) { d[t0] = d[s0] + c0; q.push(t0); } next0 = next[next0]; } } } struct Point { double x,y; }; Point seg[12000]; int n,tx,ty; const double eps = 1E-8; int sig(double d) { return (d > eps) - (d < -eps); } double dot(const Point &o,const Point&a,const Point&b) { return (a.x - o.x)*(b.x-o.x)+(a.y-o.y)*(b.y-o.y); } int btw(const Point& x,const Point&a ,const Point& b) { return sig(dot(x,a,b)); } double Cross(const Point& o,const Point& a,const Point& b) { return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); } int SegLineCross(const Point& a,const Point& b,const Point& c,const Point& d) { int d1,d2,d3,d4; d1 = sig(Cross(a,b,c)); d2 = sig(Cross(a,b,d)); d3 = sig(Cross(c,d,a)); d4 = sig(Cross(c,d,b)); if((d1^d2)==-2&&(d3^d4)==-2) return 1; if(d1==0&&btw(c,a,b)<=0 ||d2==0&&btw(d,a,b)<=0 ||d3==0&&btw(a,c,d)<=0 ||d4==0&&btw(b,c,d)<=0) return 2; return 0; } bool Test(const Point& a,const Point& b) { for(int i = 1; i <= 6 * n; i+=6) { for(int j = 0; j <=4; j+=2) { if(a.x < 2 && a.y < 3.2){ } if(SegLineCross(a,b,seg[i+j],seg[i+j+1])==1) { return false; } } } return true; } double dis(const Point& a,const Point& b) { return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); } void BuildGraph(int& cnt) { seg[cnt].x = 0; seg[cnt].y = 5; cnt++; seg[cnt].x = 10; seg[cnt].y = 5; for(int i = 1; i<=6*n; i+=6) { for(int j = 1; j<=4; j++) { Point& a = seg[i+j]; for(int m = i+6; m<=6 * n; m+=6) { for(int k = 1; k <=4; k++) { Point &b = seg[m+k]; if(Test(a,b)) { AddEdge(i+j,m+k,dis(a,b)); AddEdge(m+k,i+j,dis(a,b)); } } } if(Test(a,seg[cnt-1])) { AddEdge(i+j,cnt-1,dis(a,seg[cnt-1])); AddEdge(cnt-1,i+j,dis(a,seg[cnt-1])); } if(Test(a,seg[cnt])) { AddEdge(i+j,cnt,dis(a,seg[cnt])); AddEdge(cnt,i+j,dis(a,seg[cnt])); } } } if(Test(seg[cnt],seg[cnt-1])) { AddEdge(cnt-1,cnt,dis(seg[cnt-1],seg[cnt])); AddEdge(cnt,cnt-1,dis(seg[cnt-1],seg[cnt])); } } int main() { while(cin >> n) { if(n==-1) return 0; int cnt = 1; for(int i = 0; i < n; i++) { cin >> seg[cnt].x; seg[cnt].y = 0; for(int j = 1; j <=4; j++) { seg[cnt+j].x = seg[cnt].x; cin >> seg[cnt+j].y; } seg[cnt+5].x = seg[cnt].x; seg[cnt+5].y = 10; cnt+=6; } Init(); BuildGraph(cnt); Dijkstra(cnt,cnt-1); printf("%.2f/n",d[cnt]); } return 0; }
晓东的代码:
#include <cstdio> #include <cmath> #include <cstring> #define HEAD 100 #define EDGE 10000 using namespace std; struct Point{ double x,y; }; Point poi[18][6]; int e=0,pnt[EDGE],nxt[EDGE],head[HEAD],from[EDGE],sp[10000],n; double cost[EDGE],dis[HEAD]; bool flag[HEAD]; void addedge(int s,int t,double c){ pnt[e]=t; nxt[e]=head[s]; from[e]=s; cost[e]=c; head[s]=e; e++; } void Init(){ e=0; memset(head,-1,sizeof(head)); } int sig(double d) { return fabs(d) < 1E-6 ? 0 : d < 0 ? -1 : 1; } double cross(Point &o, Point &a, Point &b) { return (a.x - o.x)*(b.y - o.y)-(b.x - o.x)*(a.y - o.y); } int segCross(Point &a, Point &b, Point &c, Point &d) { double s1, s2; int d1, d2, d3, d4; d1 = sig(s1=cross(a,b,c)); d2 = sig(s2=cross(a,b,d)); d3 = sig(cross(c,d,a)); d4 = sig(cross(c,d,b)); if((d1^d2)==-2 && (d3^d4)==-2) return 1; return 0; } bool check(Point &a,Point &b,int xa,int xb){ for(int i=xa+1;i<xb;++i){ if(segCross(a,b,poi[i][0],poi[i][1])||segCross(a,b,poi[i][2],poi[i][3])||segCross(a,b,poi[i][4],poi[i][5])) return false; } return true; } void SPFA(int n,int s) { for(int i=0;i<=n;++i){ dis[i]=10000; flag[i]=false; } dis[s]=0; int rear=5000,front=5000; sp[++rear]=s; int s0,t0,h0,nxt0; double c0; while(front!=rear) { h0=sp[++front]; nxt0=head[h0]; flag[h0]=false; while(nxt0!=-1){ s0=from[nxt0]; t0=pnt[nxt0]; c0=cost[nxt0]; if(dis[t0]>dis[s0]+c0){ dis[t0]=dis[s0]+c0; if(!flag[t0]){ flag[t0]=true; if(dis[t0]<dis[sp[front+1]]) sp[front--]=t0; else sp[++rear]=t0; } } nxt0=nxt[nxt0]; } } } int main() { double x,a,b,c,d; Point st,en; st.x=0;st.y=5;en.x=10;en.y=5; while(scanf("%d",&n)&&n!=-1) { for(int i=0;i<n;++i) { scanf("%lf%lf%lf%lf%lf",&x,&a,&b,&c,&d); poi[i][0].x=x;poi[i][0].y=0; poi[i][1].x=x;poi[i][1].y=a; poi[i][2].x=x;poi[i][2].y=b; poi[i][3].x=x;poi[i][3].y=c; poi[i][4].x=x;poi[i][4].y=d; poi[i][5].x=x;poi[i][5].y=10; } Init(); int endN=4*n+1; if(check(st,en,-1,n)) { printf("%.2f/n",10.0); continue; } for(int i=0;i<n;++i) { for(int j=1;j<5;++j) { if(check(st,poi[i][j],-1,i)) addedge(0,4*i+j,sqrt((st.x-poi[i][j].x)*(st.x-poi[i][j].x)+(st.y-poi[i][j].y)*(st.y-poi[i][j].y))); if(check(poi[i][j],en,i,n)) addedge(4*i+j,endN,sqrt((en.x-poi[i][j].x)*(en.x-poi[i][j].x)+(en.y-poi[i][j].y)*(en.y-poi[i][j].y))); } } for(int i=0;i<n-1;++i) for(int j=1;j<5;++j) for(int k=i+1;k<n;++k) for(int m=1;m<5;++m) if(check(poi[i][j],poi[k][m],i,k)) addedge(4*i+j,4*k+m,sqrt((poi[k][m].x-poi[i][j].x)*(poi[k][m].x-poi[i][j].x)+(poi[k][m].y-poi[i][j].y)*(poi[k][m].y-poi[i][j].y))); SPFA(endN+1,0); printf("%.2f/n",dis[endN]); } return 0; }
相关文章推荐
- POJ1556(割点)
- poj1556---计算几何+最短路
- POJ1556 The Doors [线段相交 DP]
- poj1556
- POJ1556 The Doors
- Poj1556线段相交判断+动规最短路
- NYOJ 227 && poj1556 判断直线相交
- poj1556
- POJ1556---The Doors (计算几何基础:判断线段相交(快速排斥实验+跨立实验))
- poj1556
- POJ1556 计算几何+Dijkstra(邻接矩阵)
- poj1556
- POJ1556 The Doors(线段与线段相交 + 最短路
- poj1556 The Doors
- poj1556 The Doors(建图spfa+判断线段交)
- poj1556 The Doors
- POJ1556(最短路+线段相交)
- POJ1556-The Doors
- [poj1556]:The Doors
- poj1556(建图,最短路)