poj 1556 The Doors

http://poj.org/problem?id=1556

这道题目是一道图论和计算几何结合的题目,算是比较好的一道题目。

做这样的题目能够很好的理解计算几何模板的重要性,题目不是很难,主要是怎样将题目中的关键部分给分析出来,这方面我还是应该多加练习。我是用模板套的,比较好理

解,具体见代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
#define eps 1e-8
#define inf 10000000

const int maxn=120;

//定义点
struct point
{
   double x,y;
}s[maxn];

//定义线段
struct Seg
{
   point a,b;
}seg[maxn];

double cost[maxn][maxn];

//重载最大值、最小值计算函数
double min(double x,double y)
{return x<y?x:y;}
double max(double x,double y)
{return x>y?x:y;}

//判断double型的正数、负数和0,分别相应的返回1、-1和0
int dblcmp(double x)
{
   if(x==0) return 0;
   return (x>0)?1:-1;
}
//计算叉积
double det(double x1,double y1,double x2,double y2)
{return x1*y2-x2*y1;}

//计算a,b,c三点的叉积,判断a,b,c三点的位置关系
double cross(point a,point b,point c)
{return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);}

//计算两点间的最短距离
double dist(point a,point b)
{return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}

//判断线段是否相交,相交为true,不相交为false
bool segcross(point a,point b,point c,point d)
{
   int d1,d2,d3,d4;
   d1=dblcmp(cross(a,b,c));
   d2=dblcmp(cross(a,b,d));
   d3=dblcmp(cross(c,d,a));
   d4=dblcmp(cross(c,d,b));
   if((d1^d2)==-2&&(d3^d4)==-2) return true;
   return false;
}

int main()
{
   double x,y1,y2,y3,y4;
   int n;
   while(~scanf("%d",&n))
   {
      int h=0,t=1;
      s[0].x=0,s[0].y=5;
      if(n==-1) break;
      for(int i=0;i<n;i++)
      {
         cin>>x>>y1>>y2>>y3>>y4;
         s[t].x=x,s[t++].y=y1;
         s[t].x=x,s[t++].y=y2;
         s[t].x=x,s[t++].y=y3;
         s[t].x=x,s[t++].y=y4;
         seg[h].a.x=x,seg[h].a.y=0;
         seg[h].b.x=x,seg[h++].b.y=y1;
         seg[h].a.x=x,seg[h].a.y=y2;
         seg[h].b.x=x,seg[h++].b.y=y3;
         seg[h].a.x=x,seg[h].a.y=y4;
         seg[h].b.x=x,seg[h++].b.y=10;
      }
      s[t].x=10,s[t].y=5;
     
      for(int i=0;i<=t;i++)
      {
         for(int j=0;j<=t;j++)
         {
            cost[i][j]=inf;
         }
         cost[i][i]=0;
      }
     
      for(int i=0;i<=t;i++)
      {
         for(int j=0;j<=t;j++)
         {
            if(i==j) continue;
            Seg cnt;
            int k;
            cnt.a.x=s[i].x,cnt.a.y=s[i].y;
            cnt.b.x=s[j].x,cnt.b.y=s[j].y;
            for(k=0;k<h;k++)
            {
               if(segcross(cnt.a,cnt.b,seg[k].a,seg[k].b)) break;
            }
            if(k>=h) cost[i][j]=dist(cnt.a,cnt.b);
         }
      }
     
      //floyd求最短路
      for(int k=0;k<=t;k++)
      {
         for(int i=0;i<=t;i++)
         {
            for(int j=0;j<=t;j++)
            {
               if(cost[i][j]>cost[i][k]+cost[k][j])
                  cost[i][j]=cost[i][k]+cost[k][j];
            }
         }
      }
     
      printf("%.2lf\n",cost[0][t]);
   }
  
   return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值