【POJ-2653-Pick-up sticks】計算幾何+STL
阿新 • • 發佈:2018-11-01
題目連結
http://poj.org/problem?id=2653
題意
做法
程式碼
#include<stdio.h>
#include<math.h>
#include<queue>
#include<list>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps = 1e-12;
const double pi = acos(-1.0);
const int maxp = 1010;
int sgn( double x)
{
if (fabs(x) <eps) return 0;
if(x <0) return -1;
return 1;
}
struct Point
{
double x, y;
Point() {}
Point ( double _x, double _y)
{
x = _x, y = _y;
}
bool operator == (Point b) const
{
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
bool operator < (Point b) const
{
return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x;
}
Point operator - (const Point &b) const
{
return Point(x - b.x, y - b.y);
}
//叉積 |a||b|sin
double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
}
//點積 |a||b|cos 向量點積之後反過來求夾角
double operator * (const Point & b) const
{
return x * b.x + y * b.y;
}
Point operator + (const Point &b) const
{
return Point(x + b.x, y + b.y);
}
};
struct Line
{
Point s, e;
Line() {}
Line(Point _s, Point _e)
{
s = _s, e = _e;
}
//兩線段相交判斷
//2 規範相交
//1 非規範相交-過端點
//0 不相交
int segcrossseg(Line v)
{
int d1 = sgn((e-s)^(v.s-s));
int d2 = sgn((e-s)^(v.e-s));
int d3 = sgn((v.e-v.s)^(s-v.s));
int d4 = sgn((v.e-v.s)^(e-v.s));
if((d1^d2)==-2&&(d3^d4)==-2) return 2;
return ((d1==0&&sgn((v.s-s)*(v.s-e))<=0)||(d2==0&&sgn((v.e-s)*(v.e-e))<=0)||(d3==0&&sgn((s-v.s)*(s-v.e))<=0)||(d4==0&&sgn((e-v.s)*(e-v.e))<=0));
}
};
const int maxn = 1e5+10;
Line l[maxn];
vector<int>ans;
list<int> L;
void del(list<int>::iterator it)//遞迴算出所有被當前線段所影響的線段
{
Line now = l[*it];
list<int>::iterator tmp=it;
for(list<int>::iterator itt=(++it);itt!=L.end();)
{
Line nex = l[*itt];
if(now.segcrossseg(nex))
{
del(itt);//找到之後先遞迴,再將本點刪除
itt=L.erase(itt);
}
else ++itt;
}
return ;
}
int main()
{
int n;
double xa,xb,ya,yb;
while(scanf("%d",&n)!=EOF)
{
L.clear();
ans.clear();
if(n==0) break;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&xa,&ya,&xb,&yb);
l[i]=Line (Point(xa,ya),Point(xb,yb));
}
for(int i=n;i>=1;i--)
{
L.push_back(i);
}
for(list<int>::iterator it=L.begin();it!=L.end();)
{
list<int>::iterator tmp=it;
del(it);
it=++tmp;//由於有刪除操作,要先存當前指標位置,在刪除之後讓迭代器指向當前的下一位
}
L.reverse();
for(list<int>::iterator it=L.begin();it!=L.end();++it)
{
int tmp=*it;
ans.push_back(tmp);
}
sort(ans.begin(),ans.end());//保證答案有序
printf("Top sticks:");
for(int i=0;i<ans.size();i++)
{
if(i!=ans.size()-1) printf(" %d,",ans[i]);
else printf(" %d.\n",ans[i]);
}
}
return 0;
}