ACM新手DAY 26 计算几何

题解

A - TOYS

题目:给出多个区间和多个点,计算每个区间包括的点的数目

  • 计算几何+搜索
  • 判断点与线段的位置关系+二分搜索(先用二分搜索找到点大概的位置,然后用点与线段的判断找到精确位置)
//点在线段之间+二分查找
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int N = 5000+10;
int sum[N];
struct point
{
    double x,y;
    point (double X=0,double Y=0){ x=X,y=Y; }
}tmp;
struct Line
{
    point a, b;
}line[N];
double judge(point p,point p1,point p2)//把直线方程写成一般是Ax+By+c=0然后把点带入左边,
                                       //若大于0则在直线下方,若小于0则在直线上方,非向量方法
{
    return (p.x-p1.x)*(p2.y-p1.y)-(p2.x-p1.x)*(p.y-p1.y);
}
void search_(point p,int n)//二分查找部分
{
    int l=0,r=n-1;
    int mid;
    while(l<r)
    {
        mid=(l+r)>>1;
        if(judge(p,line[mid].b,line[mid].a)>0) l=mid+1;//a, b别弄反,关系着正负
        else r=mid;
    }
    if(judge(p,line[l].b,line[l].a)>0) sum[l+1]++;
    else sum[l]++;
}
int main()
{
    int n,m, bl=1;
    double x1,y1,x2,y2;
    while(~scanf("%d%d",&n, &m)&&n)
    {
        if(bl==0) printf("\n");
        memset(sum,0,sizeof(sum));

        scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
        for(int i=0; i<n; i++)
        {
            scanf("%lf %lf",&line[i].a.x, &line[i].b.x);
            line[i].a.y=y1;
            line[i].b.y=y2;
        }
        for(int i=0; i<m; i++)
        {
            double x,y;
            scanf("%lf%lf", &tmp.x, &tmp.y);
            search_(tmp,n);
        }
        for(int i=0; i<=n; i++)
        {
            printf("%d: %d\n",i,sum[i]);
        }
        bl = 0;
    }
    return 0;
}

F - Intersection

题目:确定给定线段是否与给定矩形相交

  • 注意点:1. 矩形指的是矩形平面 2.读入矩形左上和右下两个点的时候,给的顺序不一定是先左上后右下
  • 具体分析时,有如图三种情况
    在这里插入图片描述
    第一种直接用向量方法求两线段相交的模板,第二种(包括只有一个点交到的情况)就要对模板做处理,加一些东西,可以点这里(一篇关于向量法的博客)加深对代码的理解,第三种判断一下线段两个点是否在矩形里面。
#include<iostream>
#include<cstdio>
using namespace std;

const double eps = 1e-8;
int sgn(double x) {return x < -eps ? -1 : x > eps ? 1 : 0;}
struct point
{
    double x,y;
    point (double X=0,double Y=0)
    {
        x=X,y=Y;
    }
}tmp,tmp1,a[10];
typedef point Vector;

Vector operator -(Vector a,Vector b)///向量相减
{
    return Vector (a.x-b.x,a.y-b.y);
}
double cross(Vector a,Vector b)///向量叉积
{
    return a.x*b.y-a.y*b.x;
}
bool segmentproperintersection(point a1,point a2,point b1,point b2)///判断两线段相交
{
    if(min(a1.x,a2.x)>max(b1.x,b2.x)||min(a1.y,a2.y)>max(b1.y,b2.y)||min(b1.x,b2.x)>max(a1.x,a2.x)||min(b1.y,b2.y)>max(a1.y,a2.y)) return 0;
    double c1=cross(a2-a1,b1-a1), c2=cross(a2-a1,b2-a1),
           c3=cross(b2-b1,a1-b1), c4=cross(b2-b1,a2-b1);
    return sgn(c1)*sgn(c2)<=0 && sgn(c3)*sgn(c4)<=0;///等号判断边包括线段的情况,当然,前面的if处理一下特别情况
}

int solve(point now)///判一下点在不在矩形里面
{
    double x=now.x, y=now.y;
    return x>=a[1].x && x<=a[3].x && y<=a[1].y && y>=a[3].y;
}

int main()
{
    int n;
    scanf("%d",&n);
    for (int i=1; i<=n; i++)
    {
        scanf("%lf%lf",&tmp.x,&tmp.y);
        scanf("%lf%lf",&tmp1.x,&tmp1.y);//存线段的两端

        scanf("%lf%lf",&a[1].x,&a[1].y);
        scanf("%lf%lf",&a[3].x,&a[3].y);//存矩形的对角线
        if (a[1].x>a[3].x) swap(a[1].x,a[3].x);
        if (a[1].y<a[3].y) swap(a[1].y,a[3].y);
        a[2].x=a[3].x; a[2].y=a[1].y;//右上
        a[4].x=a[1].x; a[4].y=a[3].y;//左下

        int t=0;
        t+=segmentproperintersection(tmp,tmp1,a[1],a[2]);
        t+=segmentproperintersection(tmp,tmp1,a[2],a[3]);
        t+=segmentproperintersection(tmp,tmp1,a[3],a[4]);
        t+=segmentproperintersection(tmp,tmp1,a[4],a[1]);
        if (solve(tmp) && solve(tmp1)) t++;///如果线在矩形里面
        if (t) printf("T\n");
        else printf("F\n");
    }
}
发布了47 篇原创文章 · 获赞 4 · 访问量 1292

猜你喜欢

转载自blog.csdn.net/listenhhh/article/details/99319400
今日推荐