Pick-up sticks(几何:向量积,线段相交)

本文介绍了一种判断二维平面上线段是否相交的算法,并通过一个具体的编程问题“挑棍”来应用该算法。挑棍问题描述了如何找出一组随机扔在地板上的棍子中哪些是处于最上方的,即没有其他棍子覆盖的。通过使用线段相交判断的算法,我们可以有效地解决这个问题。

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

判断线段相交

struct point{
	double x,y;
};
struct line{
	point p1,p2;
}a[100010];
//叉乘 
double chacheng(point p1,point p2,point p3){
	return (p1.x-p3.x)*(p2.y-p3.y)-(p1.y-p3.y)*(p2.x-p3.x);
}
//判断是否相交 
int judge(line l1,line l2){
	if( min(l2.p1.x,l2.p2.x)<=max(l1.p1.x,l1.p2.x) 
		&& min(l2.p1.y,l2.p2.y)<=max(l1.p1.y,l1.p2.y) 
		&& min(l1.p1.x,l1.p2.x)<=max(l2.p1.x,l2.p2.x) 
		&& min(l1.p1.y,l1.p2.y)<=max(l2.p1.y,l2.p2.y) 
		&& chacheng(l1.p1,l2.p2,l2.p1)*chacheng(l1.p2,l2.p2,l2.p1)<=0 
		&& chacheng(l2.p1,l1.p2,l1.p1)*chacheng(l2.p2,l1.p2,l1.p1)<=0 )
		return 1;
	else
		return 0;
}

Pick-up sticks

题意

Stan有n根不同长度的棍子。他一次一根地将棍子随机地扔在地板上,然后,Stan试图找到在最上面的棍子,也就是没有其他的棍子压在这样的棍子上面。Stan已经注意到,最后扔出的棍子总在最上面,但他想知道所有在最上面的棍子。Stan的棍子非常地薄,其厚度可以忽略不计(如图,表示第一个样例的输入输出)。
在这里插入图片描述

输入

输入由若干测试用例组成。每个测试用例首先给出1≤n≤100000,表示这一测试用例中棍子的个数;接下来的n行每行给出4个数,这些数是一根棍子的端点的平面坐标,棍子列表的顺序是按Stan扔棍子的顺序。本题设定在最上面的棍子不超过1000根。输入以n=0结束,程序不用处理这一测试用例。

输出

对每个测试用例,输出一行,给出在最上面的棍子的列表,格式按样例。在最上面的棍子的列表顺序按Stan扔棍子的顺序。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define ll long long
int flag[100010];
struct point{
	double x,y;
};
struct line{
	point p1,p2;
}a[100010];
//叉乘 
double chacheng(point p1,point p2,point p3){
	return (p1.x-p3.x)*(p2.y-p3.y)-(p1.y-p3.y)*(p2.x-p3.x);
}
//判断是否相交 
int judge(line l1,line l2){
	if( min(l2.p1.x,l2.p2.x)<=max(l1.p1.x,l1.p2.x) 
		&& min(l2.p1.y,l2.p2.y)<=max(l1.p1.y,l1.p2.y) 
		&& min(l1.p1.x,l1.p2.x)<=max(l2.p1.x,l2.p2.x) 
		&& min(l1.p1.y,l1.p2.y)<=max(l2.p1.y,l2.p2.y) 
		&& chacheng(l1.p1,l2.p2,l2.p1)*chacheng(l1.p2,l2.p2,l2.p1)<=0 
		&& chacheng(l2.p1,l1.p2,l1.p1)*chacheng(l2.p2,l1.p2,l1.p1)<=0 )
		return 1;
	else
		return 0;
}
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		if(n==0) break;
		for(int i=0;i<n;i++)
			scanf("%lf %lf %lf %lf",&a[i].p1.x,&a[i].p1.y,&a[i].p2.x,&a[i].p2.y);
		memset(flag,0,sizeof(flag));
        for(int i=0; i<n-1; i++)
            for(int j=i+1; j<n; j++)
                if(judge(a[i],a[j]))
                {
                    flag[i]=1;
                    break;
                }
        printf("Top sticks: ");
        for(int i=0; i<n; i++)
            if(flag[i]==0)
            {
                if(i==n-1)
                    printf("%d.\n",i+1);
                else
                    printf("%d, ",i+1);
            }
	} 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值