No.10 - POJ1556 计算几何 判断点在直线

博客介绍了信息技术领域的相关计算方法,包括使用Cross函数判断点是否在直线上,利用勾股定理求斜边长度,判断墙是否阻挡两点光线,以及用Dijsktra算法计算最短路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • Cross函数判断点是否在直线上
  • 勾股定理求斜边长度
  • 判断墙是否阻挡两点光线
  • Dijsktra计算最短路
// ShellDawn
// POJ1556
// No.10

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
#define MM(x) memset(x,0,sizeof(x))
#define INF 0x3f3f3f3f
#define NINF 0xc0c0c0c0
#define eps 0.000001
using namespace std;

#define maxn 100
struct Point{
    double x;
    double y;
    void puts(const double& a,const double& b){
        x = a;
        y = b;
    }
};
struct Wall{
    Point x;
    Point y;
    void puts(const double& a,const double& b,const double& c){
        x.x = y.x = a;
        x.y = b;
        y.y = c;
    }
};
Point p[maxn];
Wall w[maxn];
int pc;
int wc;
double E[maxn][maxn];
double ans[maxn];
int visited[maxn];

// return > 0 点在直线上面
double Cross(const Point& a, const Point& b,const Point& c){
    return (b.x - a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y);
}

// a点和b点是否可以连线
bool judge(const int& a,const int& b){
    if(p[a].x - p[b].x < eps && p[b].x - p[a].x < eps) return false;
    for(int i=0;i<wc;i++){
        if(w[i].x.x > min(p[a].x,p[b].x) && w[i].x.x < max(p[a].x,p[b].x)){
            if((Cross(p[a],p[b],w[i].x)>0 && Cross(p[a],p[b],w[i].y)>0)
            || (Cross(p[a],p[b],w[i].x)<0 && Cross(p[a],p[b],w[i].y)<0)){
                continue;
            }else{
                return false;
                break;
            }
        }
    }
    return true;
}

// a点和b点距离
double PointL(const int& a,const int& b){
    return sqrt((p[a].x - p[b].x)*(p[a].x - p[b].x) + (p[a].y - p[b].y)*(p[a].y - p[b].y));
}

void Dijkstra(){
    MM(visited);
    for(int i=0;i<pc;i++) ans[i] = (int)INF;
    ans[0] = 0;
    for(int i=0;i<pc;i++){
        int loc = 0;
        double v = (int)INF;
        for(int j=0;j<pc;j++){
            if(visited[j] == 0 && ans[j] < v){
                v = ans[j];
                loc = j;
            }
        }
        visited[loc] = 1;
        for(int j=0;j<pc;j++){
            ans[j] = min(ans[j],ans[loc] + E[loc][j]);
        }
    }
}

int main(){
    int T;
    while(~scanf("%d",&T)&&T!=-1){
        pc = wc = 0;
        p[pc++].puts(0,5);
        p[pc++].puts(10,5);
        for(int i=0;i<T;i++){
            double a,b[4];
            cin>>a;
            for(int j=0;j<4;j++){
                cin>>b[j];
                p[pc++].puts(a,b[j]);
            } 
            w[wc++].puts(a,0,b[0]);
            w[wc++].puts(a,b[1],b[2]);
            w[wc++].puts(a,b[3],10);
        }
        for(int i=0;i<pc;i++){
            E[i][i] = 0;
            for(int j=i+1;j<pc;j++){
                if(judge(i,j)){
                    E[i][j] = E[j][i] = PointL(i,j);
                }else{
                    E[i][j] = E[j][i] = (int)INF;
                }
            }
        }
        Dijkstra();  
        printf("%.2f\n",ans[1]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值