【代码超详解】ZOJ 2551 / POJ 2653 Pick-up Sticks(快速排斥实验 + 跨立实验判断线段是否相交 · 模板)

博客详细解析了ZOJ 2551和POJ 2653问题,即Pick-up Sticks问题。通过`overlapped`函数判断区间是否重叠,使用快速排斥实验和跨立实验的`intersected`函数来确定线段是否相交。文章强调了在外层循环中递减处理木棍的重要性,以避免错误的相交判定和潜在的时间超限问题。

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

一、传送门

http://poj.org/problem?id=2653
https://zoj.pintia.cn/problem-sets/91827364500/problems/91827366050

二、算法分析说明与代码编写指导

overlapped 函数:
返回两个区间是否重叠。若不交,返回-1;只重叠与一点(左端区间的右端点与右端区间的左端点重合),返回0;有重叠,返回1。
cross_product:返回两个二维向量的向量积。二维向量的向量积一般定义成标量:
在这里插入图片描述
intersected 函数用快速排斥实验和跨立实验判断两条线段是否相交:
在这里插入图片描述题意:依次往地上扔棍子,问哪些棍子在棍子堆的最顶上。
考察任意两根木棍是否有交点即可。
本题中,无论是否将其中一条线段的交点为端点的情况包括在相交的范畴,都不影响 AC。
但是要注意,外层循环变量是递减的,也就是说先考察后面扔到地上的木棍再考察前面的。原因是:每根木棍只会被后面扔在它上面的木棍压住。如果两层循环的循环变量都是递增的,那么之前判定没有与其它木棍相交的木棍一旦被后来的木棍压住,就无法修正判定结果,导致 WA。当然,由于本题数据量较大,这种出错情况会导致输出的在顶上的木棍数量非常多,从而 TLE。

三、AC 代码

POJ 2653:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#pragma warning(disable:4996)
using namespace std;
template<class _Ty> struct point {
    _Ty x, y; };
struct segment {
    point<double> s, t; };
const unsigned nmax = 100001;
unsigned n; segment s[nmax]; bool top; vector<unsigned> v;
//[a1, b1] ∩ [a2, b2]
template<class _Ty> inline int overlapped(_Ty a1, _Ty b1, _Ty a2, _Ty b2) {
   
	if (a1 > b1)swap(a1, b1); if (a2 > b2)swap(a2, b2);
	_Ty m1 = (a1 + b1) / 2, m2 = (a2 + b2) / 2;
	if (m1 == m2)return b1 - a1 > 0 && b2 - a2 > 0;
	if (m1 < m2) {
   
		if (b1 < a2)return -1; if (b1 == a2)return 0;
		return 1;
	}
	if (b2 < a1)return -1; if (b2 == a1)return 0;
	return 1;
}
template<class _Ty> inline _Ty cross_product(const _Ty& x1, const _Ty& y1, const _Ty& x2, const _Ty& y2) {
   
	return x1 * y2 - x2 * y1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值