题目链接: http://poj.org/problem?id=2653
题目大意:给你几支木棒(以起点和终点的格式给出),最后问你在最上面的木棒是上面编号......
最近在敲几何模板,做做原来做过的几何题,发现了新的vector用法,vector大法好!
先理解一下vector的几个基本函数:
vector能够非常容易地添加数据,也能很方便地取出数据,同样vector提供了erase(),pop_back(),clear()来删除数据,当你删除数据的时候,你应该知道要删除尾部的数据,或者是删除所有数据,还是个别的数据。在考虑删除等操作之前让我们静下来考虑一下在STL中的一些应用。
v.erase(pointer1,pointer2) 删除pointer1到pointer2中间(包括pointer1所指)的元素。
v.clear() 删除容器中的所有元素。
vector<typeName>::iterator p=v1.begin( ); p初始值指向v1的第一个元素。
特别提醒一点:对于空的vector对象,只能用push_back这样的来添加元素,不能用下标索引
然后重点介绍一下move_if( )
Remove_if()有三个参数:
1、 iterator _First:指向第一个数据的迭代指针。
2、 iterator _Last:指向最后一个数据的迭代指针。
3、 predicate _Pred:一个可以对迭代操作的条件函数。
下面给出关于这个题目的两个vector的写法:用remove_if
#include<iostream>
#include<math.h>
#include<cstring>
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
/*
传统意义 修正写法
a == b fabs(a – b) < eps
a != b fabs(a – b) > eps
a < b a – b < -eps
a <= b a – b < eps
a > b a – b > eps
a >= b a – b > -eps
*/
#define eps 1e-8
#define zero(x) (((x)>0? (x):-(x))<eps) //是0则返回1,否则返回0
#define _sign(x) ((x)>eps? 1:((x)<-eps? 2:0))//负数 0 正数 分别返回 2 0 1
struct point {
double x;double y;
point(const double &x = 0, const double &y = 0):x(x), y(y){}
void in(){ scanf("%lf %lf", &x, &y); }
void out()const{ printf("%.2f %.2f\n",x, y);}
};
struct line {
point a,b;
int index;
line(const point &a = point(), const point &b = point()):a(a), b(b){}
void in(){ a.in(); b.in();}
void out()const{ a.out(); b.out(); }
};
//计算叉乘(P1-P0)x(P2-P0)
double xmult(point p1,point p2,point p0){ //p0是中间
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
//计算向量乘积(P1-P0).(P2-P0)
double dmult(point p1,point p2,point p0){
return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}
//两点距离
double dis(point p1,point p2){
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
//判断三点共线 共线则返回1 否则返回0
int dots_inline(point p1,point p2,point p3) {
return zero(xmult(p1,p2,p3));
}
//判断点是不是在线段上,包括端点 在线段上则返回1 否则返回0
int dot_online_in(point p,line l)
{
return zero(xmult(p,l.a,l.b))
&&(l.a.x-p.x)*(l.b.x-p.x)<eps //在l.a.x与l.b.x之间
&&(l.a.y-p.y)*(l.b.y-p.y)<eps; //在l.a.y与l.b.y之间
}
//判点是否在线段上,不包括端点
int dot_online_ex(point p,line l){
return dot_online_in(p,l)
&&(!zero(p.x-l.a.x)||!zero(p.y-l.a.y))
&&(!zero(p.x-l.b.x)||!zero(p.y-l.b.y));
}
//判两点在线段同侧,是的话返回1
int same_side(point p1,point p2,line l){
return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)>eps;
}
//判两点在线段异侧,是的话返回1
int opposite_side(point p1,point p2,line l){
return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)<-eps;
}
// 点关于直线的对称点 // by lyt
// 缺点:用了斜率
// 也可以利用"点到直线上的最近点"来做,避免使用斜率。
point symmetric_point(point p1, point l1, point l2) {
point ret;
if (l1.x > l2.x - eps && l1.x < l2.x + eps) {
ret.x = (2 * l1.x - p1.x);
ret.y = p1.y;
} else {
double k = (l1.y - l2.y ) / (l1.x - l2.x);
ret.x = (2*k*k*l1.x + 2*k*p1.y - 2*k*l1.y - k*k*p1.x + p1.x) / (1 + k*k);
ret.y = p1.y - (ret.x - p1.x ) / k;
}
return ret;
}
//判两直线平行 平行返回1
int parallel(line u,line v){
return zero((u.a.x-u.b.x)*(v.a.y-v.b.y)-(v.a.x-v.b.x)*(u.a.y-u.b.y));
}
//判两直线垂直 垂直返回1
int perpendicular(line u,line v){
return zero((u.a.x-u.b.x)*(v.a.x-v.b.x)+(u.a.y-u.b.y)*(v.a.y-v.b.y));
}
//判两线段相交,包括端点和部分重合
int intersect_in(line u,line v){
if (!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b))
return !same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u);
return dot_online_in(u.a,v)||dot_online_in(u.b,v)||dot_online_in(v.a,u)||dot_online_in(v.b,u);
}
//判两线段相交,不包括端点和部分重合
int intersect_ex(line u,line v){
return opposite_side(u.a,u.b,v)&&opposite_side(v.a,v.b,u);
}
//计算两直线交点,注意事先判断直线是否平行!
//线段交点请另外判线段相交(同时还是要判断是否平行!)
point intersection(line u,line v){
point ret=u.a;
double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))
/((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));
ret.x+=(u.b.x-u.a.x)*t;
ret.y+=(u.b.y-u.a.y)*t;
return ret;
}
//点到直线上的最近点
point ptoline(point p,line l){
point t=p;
t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
line L1(p,t);
return intersection(L1,l);
}
//点到直线距离
double disptoline(point p,line l){
return fabs(xmult(p,l.a,l.b))/dis(l.a,l.b);
}
//点到线段上的最近点
point ptoseg(point p,line l){
point t=p;
t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
if (xmult(l.a,t,p)*xmult(l.b,t,p)>eps)
return dis(p,l.a)<dis(p,l.b)?l.a:l.b;
line L1(p,t);
return intersection(L1,l);
}
//点到线段距离
double disptoseg(point p,line l){
point t=p;
t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
if (xmult(l.a,t,p)*xmult(l.b,t,p)>eps)
return dis(p,l.a)<dis(p,l.b)?dis(p,l.a):dis(p,l.b);
return fabs(xmult(p,l.a,l.b))/dis(l.a,l.b);
}
//矢量V以P为顶点逆时针旋转angle并放大scale倍
point rotate(point v,point p,double angle,double scale){
point ret=p;
v.x-=p.x,v.y-=p.y;
p.x=scale*cos(angle);
p.y=scale*sin(angle);
ret.x+=v.x*p.x-v.y*p.y;
ret.y+=v.x*p.y+v.y*p.x;
return ret;
}
line L;
bool Is_OK(line tem2)
{
return intersect_in(tem2,L)==1;
}
int main ()
{
int n;
vector<line> v;
while(scanf("%d",&n)&&n)
{
v.erase(v.begin(),v.end());
for(int i=1;i<=n;i++)
{
L.in();
L.index=i;
v.erase(remove_if(v.begin(),v.end(),Is_OK),v.end());
v.push_back(L);
}
cout << "Top sticks: ";
for(vector<line>::iterator it = v.begin(); it!= v.end(); it++)
{
cout << it->index;
if(it != v.end() -1)
cout << ", ";
else
cout << "." << endl;
}
}
}
在给出一个用erase
line L[100005];
int main()
{
int n;
double x1,x2,y1,y2;
while(scanf("%d",&n))
{
if(!n) break;
vector<int>v;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
L[i].in();
for(int j=0;j<v.size();)
{
if(intersect_in(L[i],L[v[j]]))
v.erase(v.begin()+j); // erase的实现就是往前挪, 然后释放最后一个的资源
else
j++;
}
v.push_back(i);
}
printf("Top sticks:");
for(int i=0;i<v.size()-1;i++)
printf(" %d,",v[i]);
printf(" %d.\n",v[v.size()-1]);
}
return 0;
}