• 判断线段相交 + vector. erase迭代指针 的使用 poj 2653 Pick-up sticks


    题目来源:http://poj.org/problem?id=2653

    分析:

    题意:按顺序给出一些木棍,输出在最上面的木棍标号。

    用vector 存储木棍标号, 当前木棍与 vector 中的木棍 相交,则删除该 木棍标号, 注意vector.erase(it) 中 迭代指针的使用。

    较简洁的写法:

    double add(double a, double b){
        return (fabs(a + b) < EPS * (fabs(a) + fabs(b))) ? 0 : (a + b) ;
    }
    struct Point{
        double x, y;
        Point(){}
        Point(double x, double y):x(x),y(y){}
        Point operator - (Point a){
            return Point( add(x , -a.x), add(y , -a.y)) ;
        }
        Point operator + (Point a){
            return Point( add(x , a.x), add(y , a.y)) ;
        }
        double  operator ^(Point a){
            return add(x * a.y , -y * a.x) ;
        }
    
    };
    bool on_segment(Point p1, Point p2, Point p){
        return ((p1 - p).x * (p2 - p).x <= 0 )&&((p1 - p).y * (p2 - p).y <= 0) ;
    }
    struct Line{
        Point st , ed ;
        Line(){}
        Line(Point s, Point e){
            st = s ;
            ed = e ;
        }
        bool intersection(Line l){
            Point p1, p2 ,q1 ,q2 ;
            p1  = st ;
            p2 = ed ;
            q1 = l.st ;
            q2 = l.ed ;
            double d1 ,d2 ,d3 ,d4;
            d1 = (p2 - p1)^(q1 - p1) ;
            d2 = (p2 - p1)^(q2 - p1) ;
            d3 = (q2 - q1)^(p1 - q1) ;
            d4 = (q2 - q1)^(p2 - q1) ;
            if((d1 == 0 && on_segment(p1, p2 ,q1))
               ||(d2 == 0 && on_segment(p1, p2, q2))
               || (d3 == 0 && on_segment(q1 ,q2 ,p1))
               || (d4 == 0 && on_segment(q1,q2 ,p2)) )
               return 1;
            if(d1 * d2 < 0 && d3 * d4 < 0)
                return 1;
            return 0 ;
        }
        void read(){
            scanf("%lf%lf%lf%lf" , &st.x, &st.y ,&ed.x ,&ed.y);
        }
    
    }line[Max_N];
    int n;
    bool ok(int i){
        for(int j = i+1  ; j < n ; j++){
            if(line[i].intersection(line[j]))
                return 0 ;
        }
        return 1 ;
    }
    vector<int>aa;
    vector<int>::iterator it;
    int main()
    {
        while(scanf("%d" , &n) && n){
            aa.clear() ;
            for(int i= 0 ; i < n ; i++){
                line[i].read() ;
            }
            for(int i = 0 ; i < n ; i++){
                if(ok(i))
                    aa.push_back(i) ;
            }
            printf("Top sticks");
            int flag = 0 ;
            for(it = aa.begin() ; it != aa.end() ; it++){
                    if(flag)
                        printf(",") ;
                    else printf(":") ;
                    printf(" %d", (*it + 1)) ;
                    flag = 1;
            }
            printf(".
    ") ;
        }
       return 0 ;
    }

    代码如下:

    #include <iostream>
    #include <algorithm>
    #include <stdlib.h>
    #include <stack>
    #include <iostream>
    #include <stdio.h>
    #include <string>
    #include <string.h>
    #include <algorithm>
    #include <stdlib.h>
    #include <vector>
    #include <set>
    #include <math.h>
    #include <cmath>
    #include <map>
    #include <stack>
    #include <queue>
    
    using namespace std ;
    
    double EPS=1e-10;
    // 考虑误差的加法运算
    double add(double a,double b)
    {
        if(fabs(a+b)<EPS*(fabs(a)+fabs(b))) return 0;
        return a+b;
    }
    struct Point{
        double x,y;
        Point(){}
        Point(double x,double y):x(x),y(y){} // 构造函数,方便代码编写
        Point operator +(Point p){
            return Point(add(x,p.x), add(y,p.y));
        }
        Point operator-(Point p){
            return Point(add(x,-p.x),add(y,-p.y));
        }
        Point operator*(double d){
            return Point(x*d,y*d);
        }
        double operator*(Point p){  // 内积 点乘
            return add(x*p.x, y*p.y);
        }
        double operator^(Point p){//  外积 叉乘
            return add(x*p.y,-y*p.x);
        }
    };
    //判断点p0是否在线段p1p2内
    int on_segment(Point p1, Point p2, Point p0)
    {
        if (((p1-p0).x * (p2-p0).x <=0 )&& ((p1-p0).y * (p2-p0).y <=0))   // 中间是 &&
            return 1;
        return 0;
    }
    // 判断线段p1p2与q1是否相交
    int intersection(Point p1,Point p2, Point q1,Point q2)
    {
        double d1=(p2-p1)^(q1-p1);           // 计算p1p2 到q 点的转向 d1>0 左转,  d1 <0 右转
        double d2=(p2-p1)^(q2-p1);
        double d3=(q2-q1)^(p1-q1);
        double d4=(q2-q1)^(p2-q1);
        if((d1==0 && on_segment(p1,p2,q1) )|| (d2==0 && on_segment(p1,p2,q2) )||
           (d3==0&& on_segment(q1,q2,p1)) || (d4==0 && on_segment(q1,q2,p2)))
           return 1;
        else if(d1*d2<0 && d3*d4 <0)    // 中间是 &&
            return 1;
        return 0;
    }
    
    struct Line{
           Point st ;
           Point ed ;
           Line(){}
           Line(Point a , Point b){
               st = a ;
               ed = b ;
           }
           void read(){
                scanf("%lf%lf%lf%lf" , &st.x , &st.y , &ed.x , &ed.y) ;
           }
    };
    const int N = 100010;
    Line line[N];
    vector<int>v;
    vector<int>::iterator it;
    void solve(int i)
    {
        for(it=v.begin(); it!= v.end(); )
        {
            if(intersection(line[i].st, line[i].ed,line[*it].st, line[*it].ed ) )
            {
                it=v.erase(it);     // 删除迭代指针为 it 处的元素, 并返回迭代指针。
            }
            else it++;
        }
    }
    
    int main() {
    
        int n;
        while(cin>>n && n)
        {
    
            v.clear();
            for(int i=1;i<=n;i++)
            {
                line[i].read();
    
            }
            for(int i=1;i<=n;i++)
            {
                solve(i);
                v.push_back(i);
            }
            printf("Top sticks");
            int flag=0;
            for(it=v.begin() ; it != v.end(); it++)
            {
                if(flag)
                    printf(", ");
                else printf(": ");
                printf("%d",*it);
                flag=1;
            }
    
            printf(".
    ");
        }
        return 0;
    }
  • 相关阅读:
    SQL 标准中的四种隔离级别
    java中快速排序的理解以及实例
    java中对插入排序的理解以及实例
    对冒泡排序的理解和实例
    MYSQL面试
    软件测试面试问题
    软件测试
    Linux常用命令
    关于将博客搬家至博客园的声明
    MFC常见问题以及解决方法(1)_MFC下文本编辑框按下回车后窗口退出
  • 原文地址:https://www.cnblogs.com/zn505119020/p/3625958.html
Copyright © 2020-2023  润新知