版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/83622230
题目链接:hdu 1147
题意:给你n条棒,按输入顺序投放,问最后哪些棒是最上面的,输出它们,保证输出最多不超过1000。
题解:用set容器来存放满足条件的棒。详情见代码。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#include<cmath>
using namespace std;
const int maxn=100010;
struct point{
double x,y;
point(){}
point(double _x,double _y){
x=_x;y=_y;
}
};
struct Line{
point a,b;
Line(){}
Line(point _a,point _b){
a=_a;b=_b;
}
}line[maxn];
point operator + (point a,point b) {return point(a.x+b.x,a.y+b.y);}
point operator - (point a,point b) {return point(a.x-b.x,a.y-b.y);}
point operator * (point a,double p) { return point(a.x*p,a.y*p);}
point operator / (point a,double p){ return point(a.x/p,a.y/p);}
bool operator < (const point &a,const point &b){
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
const double esp=1e-8;
int dcmp(double x){
if(fabs(x)<esp) return 0;
else return x<0?-1:1;
}
bool operator ==(const point &a,const point &b){
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Cross(point a,point b){ return a.x*b.y-a.y*b.x;}
bool isCross(point s1,point e1,point s2,point e2)///判断线段相交判定
{
///第一步,快速排斥实验
if(!(min(s1.x,e1.x)<=max(s2.x,e2.x)&&min(s2.x,e2.x)<=max(s1.x,e1.x)&&
min(s1.y,e1.y)<=max(s2.y,e2.y)&&min(s2.y,e2.y)<=max(s1.y,e1.y))) return false;
///首先判断向量s2e2 跨立 向量s1e1
double c1=Cross(s2-s1,e1-s1),c2=Cross(e1-s1,e2-s1);
///再次判断向量s1e1 跨立 向量 s2e2
double c3=Cross(s1-s2,e2-s2),c4=Cross(e2-s2,e1-s2);
///==0表示,相交于端点也认定为相交
// printf("c1=%f,c2=%f,c3=%f,c4=%f\n",c1,c2,c3,c4);
if(dcmp(c1*c2)>=0&&dcmp(c3*c4)>=0) return true;
return false;
}
set<int> myset;
set<int> ::iterator it,it2;
int storage[1100];
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
double x1,y1,x2,y2;
myset.clear();
for(int i=0;i<n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[i]=Line(point(x1,y1),point(x2,y2));
}
myset.insert(0); ///第一条棒存进去
for(int i=1;i<n;i++)
{
bool flag=true;
int tot=0;
for(it=myset.begin();it!=myset.end();it++) ///与之前顶部棒判断是否有相交
{
int item=*it;
if(isCross(line[i].a,line[i].b,line[item].a,line[item].b)){
// printf("i=%d,item=%d\n",i,item);
storage[tot++]=*it; ///有交叉,记录下来
}
}
myset.insert(i); ///最后的肯定不会被相交,故放进去
for(int j=0;j<tot;j++){
myset.erase(storage[j]); ///删除容器内被相交的
}
}
// printf("%d\n",myset.size());
printf("Top sticks:");
it2=myset.end();
it2--;
for(it=myset.begin();it!=it2;it++)
printf(" %d,",*it+1);
printf(" %d.\n",*(myset.rbegin())+1);
}
return 0;
}