最长的相交线段---2014亚马逊机试第2题

本文介绍了一种判断二维平面上两条线段是否相交的方法,包括快速排斥试验和跨立试验两个步骤,并提供了一个C++实现示例。

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


判断连个线段是否相交,分为两步:

(1).快速排斥试验
设以线段 P1P2 为对角线的矩形为R, 设以线段 Q1Q2 为对角线的矩形为T,如果R和T不相交,显然两线段不会相交;
(2).跨立试验
如果两线段相交,则两线段必然相互跨立对方,P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ) 和( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,即
( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0
上式可改写成
( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0
当( P1 - Q1 ) × ( Q2 - Q1 ) = 0 时,说明( P1 - Q1 ) 和 ( Q2 - Q1 )共线,但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;
同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2上。
所以判断P1P2跨立Q1Q2的依据是:
( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) ≥ 0
同理判断Q1Q2跨立P1P2的依据是:
( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) ≥ 0

// segmentLine.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <set>
#include <math.h>

using namespace std;

bool JudgeStatus(double line01Coords[], double line02Coords[])
{
	bool returnResult = true;
	//先判断在XY方向的最值
	double maxX1, minX1, maxY1, minY1;
	maxX1 = minX1 = line01Coords[0];
	maxY1 = minY1 = line01Coords[1];
	if (line01Coords[0] < line01Coords[2])
		maxX1 = line01Coords[2];
	else
		minX1 = line01Coords[2];
	if (line01Coords[1] < line01Coords[3])
		maxY1 = line01Coords[3];
	else
		minY1 = line01Coords[3];
	double maxX2, minX2, maxY2, minY2;
	maxX2 = minX2 = line02Coords[0];
	maxY2 = minY2 = line02Coords[1];
	if (line02Coords[0] < line02Coords[2])
		maxX2 = line02Coords[2];
	else
		minX2 = line02Coords[2];
	if (line02Coords[1] < line02Coords[3])
		maxY2 = line02Coords[3];
	else
		minY2 = line02Coords[3];
	//比较最值大小
	if ((minX1 > maxX2) || (maxX1 < minX2) || (minY1 > maxY2) || (maxY1 < minY2))
	{
		returnResult = false;
	}
	return returnResult;
}

typedef struct{
	double x;
	double y;
}point;
bool lineCross(double line1[], double line2[])
{
	bool returnResult;
	returnResult = JudgeStatus(line1, line2);
	if(returnResult == true)
	{
		point p1,p2,p3,p4;
		point v1,v2,v3;
		p1.x = line1[0];
		p1.y = line1[1];
		p2.x = line1[2];
		p2.y = line1[3];
		p3.x = line2[0];
		p3.y = line2[1];
		p4.x = line2[2];
		p4.y = line2[3];
		v1.x = p2.x - p1.x;
		v1.y = p2.y - p1.y;
		v2.x = p3.x - p1.x;
		v2.y = p3.y - p1.y;
		v3.x = p4.x - p1.x;
		v3.y = p4.y - p1.y;
		double cross_mult1 = v1.x *v2.y - v1.y*v2.x;
		double cross_mult2 = v1.x *v3.y - v1.y*v3.x;
		double cross1 = cross_mult1*cross_mult2;

		v1.x = p4.x - p3.x;
		v1.y = p4.y - p3.y;
		v2.x = p1.x - p3.x;
		v2.y = p1.y - p3.y;
		v3.x = p2.x - p3.x;
		v3.y = p2.y - p3.y;
		double cross_mult3 = v1.x *v2.y - v1.y*v2.x;
		double cross_mult4 = v1.x *v3.y - v1.y*v3.x;
		double cross2 = cross_mult3*cross_mult4;
		if(cross1<=0 && cross1 <=0)
		{
			return true;
		}
	}
	return false;
}

double culculate(double line[])
{
	double r;
	r =sqrt( pow(float(line[0]-line[2]),2) + pow(float(line[1]-line[3]),2));
	return r;
}
void main()
{
	int line_num;
	int i;
	double line_points[100][4];
	vector<int> temp;
	vector<int> remain;
	scanf("%d",&line_num);
	for(i=0; i < line_num; i++)
	{
		for(int j = 0; j < 4; j++)
		{
			scanf("%lf,",&(line_points[i][j]));
		}
	}
	for(i=0; i < line_num; i++)
	{
		for(int j = 0; j < 4; j++)
		{
			printf("%lf ",line_points[i][j]);
		}
		printf("\n");
	}
	int count = line_num;
	double maxLen=-1;
	double len=0;

	for(i = 0; i < line_num; i++)
	{
		remain.push_back(i);
	}
	while(!remain.empty())
	{
		int kk = *(remain.begin());
		len = culculate(line_points[kk]);
		temp.clear();
		temp.push_back(kk);
		std::vector<int>::iterator it = remain.begin();
		remain.erase(it);
		for(vector<int>::iterator ite = remain.begin(); ite != remain.end();)
		{
			bool flag = false;
			for(std::vector<int>::iterator it_temp = temp.begin(); it_temp!= temp.end(); it_temp++)
			{
				if(lineCross(line_points[*it_temp],line_points[*ite]))
				{
					flag = true;
					break;
				}
			}
			if(flag)
			{
				len += culculate(line_points[*ite]);
				temp.push_back(*ite);
				ite = remain.erase(ite);
			}
			else{ite++;}
		}
		printf("\n");
		
		if(len > maxLen)
		{
			maxLen = len;
		}
	}
	printf("%lf",maxLen);
	while(1);
}


注意:使用容器的erase函数在for循环中删除元素时,使用:

for(ite = v.begin(); ite != v.end();) 
{
    if(*ite == 1){ ite = v.erase(ite); }
    else{ite ++;}
       
}

基于SpringBoot的在线网络学习平台研究AI更换标第1章引言介绍基于SpringBoot的在线网络学习平台的研究背景、意义、国内外现状、论文研究方法及创新点。1.1研究背景与意义阐述在线网络学习平台的重要性及其在教育领域的应用价值。1.2国内外研究现状分析当前国内外在线网络学习平台的发展状况及趋势。1.3研究方法与创新点说明本研究采用的方法论和在研究过程中的创新之处。第2章相关理论技术概述SpringBoot框架、在线教育理论及相关技术基础。2.1SpringBoot框架概述介绍SpringBoot框架的特点、优势及其在Web应用中的作用。2.2在线教育理论阐述在线教育的基本理念、教学模式及其与传统教育的区别。2.3相关技术基础介绍开发在线网络学习平台所需的关键技术,如前端技术、数据库技术等。第3章在线网络学习平台设计详细描述基于SpringBoot的在线网络学习平台的整体设计方案。3.1平台架构设计给出平台的整体架构图,并解释各个模块的功能及相互关系。3.2功能模块设计详细介绍平台的主要功能模块,如课程管理、用户管理、在线考等。3.3数据库设计说明平台的数据库设计方案,包括数据表结构、数据关系等。第4章平台实现与测阐述平台的实现过程及测方法。4.1平台实现详细介绍平台的开发环境、开发工具及实现步骤。4.2功能测对平台的主要功能进行测,确保功能正常且符合预期要求。4.3性能测对平台的性能进行测,包括响应时间、并发用户数等指标。第5章平台应用与分析分析平台在实际应用中的效果及存在的问,并提出改进建议。5.1平台应用效果介绍平台在实际教学中的应用情况,包括用户反馈、使用情况等。5.2存在问及原因分析分析平台在运行过程中出现的问及其原因,如技术瓶颈、用户体验等。5.3改进建议与措施针对存在的问提出具体的改进建议和措施,以提高平台的性能和用户满意度
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值