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。
POJ 2653:
#include
#include
#include
#include
#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;
}
//if segment ab is intersected with segment cd
template<class _Ty> inline bool intersected(const point<_Ty>& a, const point<_Ty>& b, const point<_Ty>& c, const point<_Ty>& d) {
if (overlapped(a.x, b.x, c.x, d.x) != 1)return false;
if (overlapped(a.y, b.y, c.y, d.y) != 1)return false;
_Ty u1 = b.x - a.x, u2 = b.y - a.y, v1 = d.x - c.x, v2 = d.y - c.y;
if (cross_product(u1, u2, c.x - a.x, c.y - a.y) * cross_product(u1, u2, d.x - a.x, d.y - a.y) >= 0)return false;
if (cross_product(v1, v2, a.x - c.x, a.y - c.y) * cross_product(v1, v2, b.x - c.x, b.y - c.y) >= 0)return false;
return true;
}
int main() {
for (;;) {
scanf("%u", &n); if (n == 0)return 0;
for (unsigned i = 1; i <= n; ++i)scanf("%lf%lf%lf%lf", &s[i].s.x, &s[i].s.y, &s[i].t.x, &s[i].t.y);
v.clear(); v.push_back(n);
for (unsigned i = n - 1; i; --i) {
top = true;
for (unsigned j = i + 1; j <= n; ++j) {
if (intersected(s[i].s, s[i].t, s[j].s, s[j].t)) { top = false; break; }
}
if (top)v.push_back(i);
}
printf("Top sticks: %u", *v.rbegin());
for (vector<unsigned>::reverse_iterator i = v.rbegin() + 1; i != v.rend(); ++i)printf(", %u", *i);
puts(".");
}
}
ZOJ 2551:
#include
#include
#include
#include
#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;
}
//if segment ab is intersected with segment cd
template<class _Ty> inline bool intersected(const point<_Ty>& a, const point<_Ty>& b, const point<_Ty>& c, const point<_Ty>& d) {
if (overlapped(a.x, b.x, c.x, d.x) != 1)return false;
if (overlapped(a.y, b.y, c.y, d.y) != 1)return false;
_Ty u1 = b.x - a.x, u2 = b.y - a.y, v1 = d.x - c.x, v2 = d.y - c.y;
if (cross_product(u1, u2, c.x - a.x, c.y - a.y) * cross_product(u1, u2, d.x - a.x, d.y - a.y) >= 0)return false;
if (cross_product(v1, v2, a.x - c.x, a.y - c.y) * cross_product(v1, v2, b.x - c.x, b.y - c.y) >= 0)return false;
return true;
}
int main() {
for (;;) {
scanf("%u", &n); if (n == 0)return 0;
for (unsigned i = 1; i <= n; ++i)scanf("%lf%lf%lf%lf", &s[i].s.x, &s[i].s.y, &s[i].t.x, &s[i].t.y);
v.clear(); v.emplace_back(n);
for (unsigned i = n - 1; i; --i) {
top = true;
for (unsigned j = i + 1; j <= n; ++j) {
if (intersected(s[i].s, s[i].t, s[j].s, s[j].t)) { top = false; break; }
}
if (top)v.emplace_back(i);
}
printf("Top sticks: %u", *v.crbegin());
for (auto i = v.crbegin() + 1; i != v.crend(); ++i)printf(", %u", *i);
puts(".");
}
}