poj1156

一道图论和计算几何综合的题

题意很好理解,略

【解答】

把墙上的所有可以走的点作为图中的点,建边的时候用线段相交判断是否可以连边。

在跑一次dijkstra即可得解。注意,线段相交的时候,端点不算。

水题,可以作为练手的题。

#include <iostream>
#include <cmath>
#define eps 1e-8
using namespace std;
const int maxn=300;
const double oo=1e8;
struct point
{
       double x,y;
}p[maxn];
struct line
{
       point a,b;
}w[maxn];
double a[maxn][maxn],d[maxn];
int v[maxn];
int tot,ss,n;
double xmult(point p1,point p2,point p0)
{
       return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
double dist(point a,point b)
{
       return sqrt(double((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y)));
}
int opposite_side(point p1,point p2,point l1,point l2)
{
    return xmult(p1,l2,l1)*xmult(p2,l2,l1)<-eps;
}
int intersect_ex(point u1,point u2,point v1,point v2)
{
    return opposite_side(u1,u2,v1,v2) && opposite_side(v1,v2,u1,u2);
}
void init()
{
     p[0].x=0;p[0].y=5;
     for (int i=0;i<n;i++)
     {
         double xx,a,b,c,d;
         cin >> xx >> a >> b >> c >> d;
         w[tot].a.x=xx;w[tot].a.y=0;w[tot].b.x=xx;w[tot++].b.y=a;
         w[tot].a.x=xx;w[tot].a.y=b;w[tot].b.x=xx;w[tot++].b.y=c;
         w[tot].a.x=xx;w[tot].a.y=d;w[tot].b.x=xx;w[tot++].b.y=10;
         p[ss].x=xx;p[ss++].y=a;
         p[ss].x=xx;p[ss++].y=b;
         p[ss].x=xx;p[ss++].y=c;
         p[ss].x=xx;p[ss++].y=d;              
     }   
     p[ss].x=10;p[ss].y=5;
}  
void build()
{
     int i,j,k,ff;
     for (i=0;i<=ss;i++)
         for (j=0;j<=ss;j++)
             if (i==j) a[i][j]=0;
             else a[i][j]=oo;
     for (i=0;i<=ss;i++)
         for (j=0;j<=ss;j++)
         {
             if (i==j) continue;
             ff=1;
             for (k=0;k<tot;k++)
                 if (intersect_ex(p[i],p[j],w[k].a,w[k].b))
                    ff=0;
             if (ff) a[i][j]=dist(p[i],p[j]);
         }     
}
double dijkstra()
{
     double mi;
     int i,k;
     for (i=0;i<=ss;i++)
         d[i]=oo,v[i]=0;
     d[0]=0;
     while (1)
     {
           k=-1;mi=oo;
           for (i=0;i<=ss;i++)
           if (d[i]<mi && !v[i])
              mi=d[i],k=i;
           if (k==-1) break;
           v[k]=1;
           for (i=0;i<=ss;i++)
               if (d[k]+a[k][i]<d[i])
                  d[i]=d[k]+a[k][i];
     }
     return d[ss];
}
int main()
{
    freopen("pin.txt","r",stdin);
    freopen("pou.txt","w",stdout);
    while (cin >> n && n!=-1)
    {
          tot=0,ss=1;
          init();
          build();
          cout.precision(2);
          cout.setf(ios_base::floatfield,ios_base::fixed);
          cout << dijkstra() << endl;    
    }      
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值