惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V2EX - 技术
V2EX - 技术
P
Privacy International News Feed
Security Latest
Security Latest
H
Hacker News: Front Page
T
Tenable Blog
The Hacker News
The Hacker News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Security @ Cisco Blogs
Project Zero
Project Zero
O
OpenAI News
AI
AI
Spread Privacy
Spread Privacy
C
CERT Recently Published Vulnerability Notes
The Last Watchdog
The Last Watchdog
G
GRAHAM CLULEY
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Scott Helme
Scott Helme
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
CXSECURITY Database RSS Feed - CXSecurity.com
NISL@THU
NISL@THU
A
Arctic Wolf
T
Threat Research - Cisco Blogs
PCI Perspectives
PCI Perspectives
N
News and Events Feed by Topic
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
Simon Willison's Weblog
Simon Willison's Weblog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
Google Online Security Blog
Google Online Security Blog
罗磊的独立博客
L
LINUX DO - 最新话题
U
Unit 42
S
Security Affairs
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
博客园 - 【当耐特】
T
The Exploit Database - CXSecurity.com
S
Schneier on Security
月光博客
月光博客
Engineering at Meta
Engineering at Meta
腾讯CDC
F
Full Disclosure
Cyberwarzone
Cyberwarzone
S
SegmentFault 最新的问题
Recorded Future
Recorded Future
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 司徒正美
The Cloudflare Blog

博客园 - woodfish

偏序集的Dilworth定理 XJOJ历经2个月终于完成啦~~ fork()调用的一个趣题 实现google那种输入框提示的功能 POJ 3691 安徽第二题 有限状态自动机+DP 哈尔滨赛区网络预选赛总结 [计算几何]点集中的点能组成多少个正方形 [计算几何]POJ 1375 点对圆的切线+线段重叠 [计算几何] POJ 1873 暴力+凸包 [计算几何]POJ 1266 三角形的外接圆 圆的参数方程 POJ 1026 置换群 [计算几何]POJ 1031 计算点对多边形的偏转角度 [计算几何]POJ2079 求点集中面积最大的三角形 [计算几何]POJ3608 求2个不相交凸包的最短距离 [计算几何]凸包的旋转卡壳算法 C++禁止一个类被继承的技术 C与汇编的接口技术 计算位数的3种方法 避免使用条件分支
[计算几何]POJ 1556 判断线段相交+Dijkstra
woodfish · 2008-09-09 · via 博客园 - woodfish

http://acm.pku.edu.cn/JudgeOnline/problem?id=1556

挺有意思的一个题。

 

题目大意如上图,有一个房间,要从(0,5)走到(10,5),房间内有一些竖直的墙壁,现在要求最短的路径长度。

首先,很直观很显然的,要使路径达到最短,我们每次都是沿着墙的端点按直线走,也就是从一个墙的端点走到另一个墙的端点,这样问题就可以转换为图论中的最短路问题了,设上图中有n个端点,这样可以建立一个n+2个点的有向带权图g,g[i][j]表示从端点i到端点j的长度。

下面是关于怎么构图:枚举2个端点i和j,如果线段Pi->Pj于横坐标处于Xi,Xj之间的墙壁都没有相交的话,则可以从端点i直线走到端点j,在图g中假如一条由i指向j的边,权值为distance(Pi,Pj)。

这样,最构造出来的图求最短路就可以得到最后问题的解了。

#include <iostream>
#include 
<string>
#include 
<cstdio>
#include 
<cmath>
using namespace std;
#define EPS 1.0e-6struct Point {
    
double x,y;
};
int dblcmp(double r) {
    
if(fabs(r)<EPS) return 0;
    
return r>0?1:-1;
}
double dot(double x1,double y1,double x2,double y2) {
    
return x1*y2-x2*y1;
}
double cross(Point a,Point b,Point c) {
    
return dot(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
//判断线段(a,b)和(c,d)是否相交(不算端点)
bool lineseg(Point a,Point b,Point c,Point d) {
    
return (((dblcmp(cross(a,b,c))^dblcmp(cross(a,b,d)))==-2)
                
&&((dblcmp(cross(c,d,a))^dblcmp(cross(c,d,b)))==-2));
}
double mydist(Point a,Point b) {
    
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double g[200][200];    //图的临街矩阵
int s,t;
int n;
Point line[
200][2];    //存储墙
Point pts[200];        //存储墙2端的端点

int main() {
    
double x,y1,y2,y3,y4;
    
while(cin>>n) {
        
if(n==-1break;
        s
=0,t=4*n+1;
        pts[
0].x=0;
        pts[
0].y=5;
        pts[t].x
=10;
        pts[t].y
=5;for(int i=0;i<n;i++) {
            cin
>>x>>y1>>y2>>y3>>y4;
        
            line[i
*3][0].x=x;
            line[i
*3][0].y=0;
            line[i
*3][1].x=x;
            line[i
*3][1].y=y1;

            line[i

*3+1][0].x=x;
            line[i
*3+1][0].y=y2;
            line[i
*3+1][1].x=x;
            line[i
*3+1][1].y=y3;

            line[i

*3+2][0].x=x;
            line[i
*3+2][0].y=y4;
            line[i
*3+2][1].x=x;
            line[i
*3+2][1].y=10;

            pts[

4*i+1].x=x;
            pts[
4*i+1].y=y1;
            pts[
4*i+2].x=x;
            pts[
4*i+2].y=y2;
            pts[
4*i+3].x=x;
            pts[
4*i+3].y=y3;
            pts[
4*i+4].x=x;
            pts[
4*i+4].y=y4;
        }
        
for(int i=s;i<=t;i++)
            
for(int j=s;j<=t;j++)
                g[i][j]
=1.0e10;
        
//下面建图
        for(int i=0;i<=t;i++) {
            
for(int j=i+1;j<=t;j++) {
                
bool ok=true;
                
for(int k=0;k<3*n;k++) {
                    
if(pts[i].x!=pts[j].x&&pts[i].x!=line[k][0].x&&pts[j].x!=line[k][0].x&&lineseg(pts[i],pts[j],line[k][0],line[k][1])) {
                        ok
=false;
                        
break;
                    }
                }
                
if(ok) {
                    g[i][j]
=mydist(pts[i],pts[j]);
                }
            }
        }
//下面用Dijkstra算法求最短路
        double dist[200];
        
for(int i=s;i<=t;i++) dist[i]=1.0e10;
        dist[
0]=0;
        
bool vis[200];
        memset(vis,
false,sizeof(vis));
        
for(int i=s;i<=t;i++) {
            
double mind=1.0e10;
            
int id;
            
for(int j=s;j<=t;j++) {
                
if(!vis[j]&&mind>dist[j]) {
                    id
=j;
                    mind
=dist[j];
                }
            }
            
if(mind==1.0e10break;
            vis[id]
=true;
            
for(int j=s;j<=t;j++) {
                
if(!vis[j]&&dist[id]+g[id][j]<dist[j]) {
                    dist[j]
=dist[id]+g[id][j];
                }
            }
        }

        printf(

"%.2f\n",dist[t]);
    }
    
return 0;
}