zoukankan      html  css  js  c++  java
  • codeForce-589D Boulevard(判断线段是否相交)

    题目大意:n个人、一个区间。每个人都会在某个时间段内按相同的速度(所有人的速度都一样,都是1或-1)在他的区间内从一个端点走到另一个端点(只走一次)。问每个人会与几个人碰面。

    题目分析:将时间看成一个维度,区间位置看成另一个维度。那么每个人的状态便构成了一条二维线段。只需判断有几条线段与该线段相交。

    判断两平面线段是否相交:

    设线段1的两端点分别为A、B,线段2的两端点分别为C、D。

    当两条线段平行时,只需要判断点C或点D是否在线段AB上即可。点C在线段AB上的判断:先判断向量CA与向量CB是否共线,如果共线只需判断C是否在以A、B为对顶点的矩形区域中;否则C不再线段AB上。

    当两条线段不平行时:AB与CD相交的充分必要条件是direct(AC,AD)!=direct(BC,BD)且direct(CA,CB)!=direct(DA,DB),其中direct(L1,L2)表示将向量L1以最小的旋转角度旋转到与向量L2共线时采取的旋转方向(逆时针或顺时针)。通过观察可以知道,如果逆时针旋转,那么L1与L2的夹角小于等于180°,否则大于180°。只需要知道夹角的正弦值的符号即可判断方向。设L1=(x1,y1),L2=(x2,y2),通过几步简单的化简可以得到两向量L1、L2的夹角正弦值只与x1*y2-x2*y1,即两向量叉积,有关。

    详细请参考:https://segmentfault.com/a/1190000004457595

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<string>
    # include<map>
    # include<vector>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    # define LL long long
    
    struct Person
    {
    	int t,s,f,id;
    };
    Person p[1005];
    int ans[1005];
    
    bool comp(const Person &p1,const Person &p2)
    {
    	return p1.t<p2.t;
    }
    
    int f(LL x)
    {
    	if(x>0) return 1;
    	if(x<0) return -1;
    	return 0;
    }
    
    int direct(int x1,int y1,int x2,int y2)
    {
    	return f((LL)x1*(LL)y2-(LL)x2*(LL)y1);
    }
    
    bool inSegment(int ax,int ay,int bx,int by,int cx,int cy)
    {
    	if(direct(ax-cx,ay-cy,bx-cx,by-cy)) return false;
    	if(cx<min(ax,bx)) return false;
    	if(cx>max(ax,bx)) return false;
    	if(cy<min(ay,by)) return false;
    	if(cy>max(ay,by)) return false;
    	return true;
    }
    
    bool meet(int i,int j)
    {
    	int ax=p[i].t,ay=p[i].s;
    	int bx=p[i].t+abs(p[i].f-p[i].s),by=p[i].f;
    	int cx=p[j].t,cy=p[j].s;
    	int dx=p[j].t+abs(p[j].f-p[j].s),dy=p[j].f;
    	
    	///处理向量共线时
    	int ABx=bx-ax,ABy=by-ay;
    	int CDx=dx-cx,CDy=dy-cy;
    	if(direct(ABx,ABy,CDx,CDy)==0){
    		return inSegment(ax,ay,bx,by,cx,cy)||inSegment(ax,ay,bx,by,dx,dy);
    	}
    	
    	int AC_AD=direct(cx-ax,cy-ay,dx-ax,dy-ay);
    	int BC_BD=direct(cx-bx,cy-by,dx-bx,dy-by);
    	int CA_CB=direct(ax-cx,ay-cy,bx-cx,by-cy);
    	int DA_DB=direct(ax-dx,ay-dy,bx-dx,by-dy);
    	
    	return AC_AD*BC_BD<=0&&CA_CB*DA_DB<=0;
    }
    
    int main()
    {
    	int n;
    	while(~scanf("%d",&n))
    	{
    		for(int i=0;i<n;++i){
    			scanf("%d%d%d",&p[i].t,&p[i].s,&p[i].f);
    			p[i].id=i;
    		}
    		sort(p,p+n,comp);
    		memset(ans,0,sizeof(ans));
    		for(int i=0;i<n;++i) for(int j=i+1;j<n;++j) if(meet(i,j))
    			++ans[p[i].id],++ans[p[j].id];
    		for(int i=0;i<n;++i)
    			printf("%d%c",ans[i],(i==n-1)?'
    ':' ');
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    《父亲写的散文诗》--许飞
    python 解数独
    github key already in use
    openwrt ddns绑定域名
    hexo 长期后台运行
    修复云服务器rpm无法使用的问题
    vim 取消筛选高亮
    力扣 2021.02.25 最长公共前缀
    [模板]-Manacher
    背包问题回顾
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5794058.html
Copyright © 2011-2022 走看看