hdu 1147 Pick-up sticks (判斷線段是否相交)
阿新 • • 發佈:2018-11-05
題目連結: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; }