题目大意:按顺序放木棒,问最后所有的木棒中上面没有木棒的木棒的索引是……
思路:按理说线段相交的题目做的听多了,这个应该不算新鲜,但是这个题,还是让我学到了认真读题,面对这个题很容易想到对于新输入的一根木棒,遍历它前面所有的木棒,判断是否有重合的有的话,把那个被重合木棒的索引标记好,这样是很好的但是两层循环就差不多是1e5 * (1 ~ 1e5)的复杂度了,所以看题看题:题目说,最后符合要求的木棒m < 1e3 ,就代表我们第二个循环可以是(1~ 1e3)的操作(前提,数据不算太暴力),所以,我们就可以记录索引,如果发现一个木棒已经作废,那我们就可以代替它,把新的木棒加到它的位置~~
code~~
正常的准备
#include <iostream> #include <algorithm> #include <vector> #define eps 1e-10 using namespace std; const int maxn = 1e5 + 1e2; const int maxm = 1e3 + 1e2; struct Point { double x,y; Point(double x = 0.0,double y = 0.0):x(x),y(y){} Point operator - (Point p){return Point(x - p.x,y - p.y);} }; struct segment { Point p1,p2; segment (Point p1 = Point(0.0,0.0),Point p2 = Point(0.0,0.0)):p1(p1),p2(p2){} }lset[maxn]; double cross(Point p0,Point p1,Point p2) { Point a = p1 - p0; Point b = p2 - p0; return a.x * b.y - b.x * a.y; } vector<int> ans;
线段相交的判断
bool interset(segment s1,segment s2) { int flag = 0; if(cross(s1.p1,s1.p2,s2.p1) * cross(s1.p1,s1.p2,s2.p2) < eps)flag++; if(cross(s2.p1,s2.p2,s1.p1) * cross(s2.p1,s2.p2,s1.p2) < eps)flag++; if(flag == 2)return true; return false; }
main函数
int main() { int n; double x1,y1,x2,y2; while(~scanf("%d",&n),n) { ans.clear(); for(int i = 1;i <= n;i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); lset[i] = segment(Point(x1,y1),Point(x2,y2)); int idx = -1; for(int j = 0;j < ans.size();j++) { if(ans[j] == -1)idx = j; else if(interset(lset[i],lset[ans[j]]))ans[j] = -1; } if(idx != -1)ans[idx] = i; else ans.push_back(i); } sort(ans.begin(),ans.end()); printf("Top sticks: "); for(int i = 0;i < ans.size() - 1;i++) { if(ans[i] != -1)printf("%d, ",ans[i]); } printf("%d. ", ans[ans.size() - 1]); } return 0; }
idx就是待寻找的索引,初始化为-1也就是一个flag标志,不是-1代表有可替代的木棒,最后需要费时间排序一下
越来越喜欢模块化编程了,特别是自己打出来的代码,不整齐,不模块化,反而很不舒服,以前我还是一main到底,这就是进步吧,加油~