题目大意:按顺序放木棒,问最后所有的木棒中上面没有木棒的木棒的索引是……
思路:按理说线段相交的题目做的听多了,这个应该不算新鲜,但是这个题,还是让我学到了认真读题,面对这个题很容易想到对于新输入的一根木棒,遍历它前面所有的木棒,判断是否有重合的有的话,把那个被重合木棒的索引标记好,这样是很好的但是两层循环就差不多是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.\n", ans[ans.size() - 1]);
}
return 0;
}
idx就是待寻找的索引,初始化为-1也就是一个flag标志,不是-1代表有可替代的木棒,最后需要费时间排序一下
越来越喜欢模块化编程了,特别是自己打出来的代码,不整齐,不模块化,反而很不舒服,以前我还是一main到底,这就是进步吧,加油~