【几何训练】poj 2653

题目链接: 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;
}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值