您的位置:首页 > 其它

poj1556

2010-10-13 21:17 113 查看
题意:房间里有n堵墙,每面墙上有两扇门,求从房间最左端中点到最右端中点的最短路径

心得:解析很简单,简单的计算几何+简单的最短路径

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: