题目大意: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)?'\n':' ');
}
return 0;
}

  

codeForce-589D Boulevard(判断线段是否相交)的更多相关文章

  1. Any Way You Slice It (向量旋转 以及 判断线段是否相交)(模板)

    http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11353 #include<iostream> # ...

  2. Jack Straws(判断线段是否相交 + 并查集)

    /** http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1840    题意:    判断线段 ...

  3. HDU 1086 You can Solve a Geometry Problem too( 判断线段是否相交 水题 )

    链接:传送门 题意:给出 n 个线段找到交点个数 思路:数据量小,直接暴力判断所有线段是否相交 /*************************************************** ...

  4. zoj 1648 判断线段是否相交

    链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=648 Circuit Board Time Limit: 2 Second ...

  5. 还记得高中的向量吗?leetcode 335. Self Crossing(判断线段相交)

    传统解法 题目来自 leetcode 335. Self Crossing. 题意非常简单,有一个点,一开始位于 (0, 0) 位置,然后有规律地往上,左,下,右方向移动一定的距离,判断是否会相交(s ...

  6. POJ 2653 Pick-up sticks (判断线段相交)

    Pick-up sticks Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 10330   Accepted: 3833 D ...

  7. 判断线段相交(hdu1558 Segment set 线段相交+并查集)

    先说一下题目大意:给定一些线段,这些线段顺序编号,这时候如果两条线段相交,则把他们加入到一个集合中,问给定一个线段序号,求在此集合中有多少条线段. 这个题的难度在于怎么判断线段相交,判断玩相交之后就是 ...

  8. POJ 2556 (判断线段相交 + 最短路)

    题目: 传送门 题意:在一个左小角坐标为(0, 0),右上角坐标为(10, 10)的房间里,有 n 堵墙,每堵墙都有两个门.每堵墙的输入方式为 x, y1, y2, y3, y4,x 是墙的横坐标,第 ...

  9. 51node1264(判断线段相交)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1264 题意:中文题诶- 思路:对于直线a1a2, b1b2, ...

随机推荐

  1. [luogu2982][USACO10FEB]慢下来Slowing down(树状数组+dfs序)

    题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) cows conveniently numbered 1..N mov ...

  2. LTE Module User Documentation(翻译12)——X2切换(X2-based handover)

    LTE用户文档 (如有不当的地方,欢迎指正!) 18 X2-based handover   正如 3GPP 定义的,切换是改变用户服务小区的连接方式的过程.这一过程中涉及的两个基站通常称为源基站和目 ...

  3. 查看rpm和war包内容

    解压rpm包的内容:(没有安装,就像解压tgz包一样rpm包)rpm2cpio *.rpm | cpio -div 解压war包的内容: jar -xvf project.war 解压到当前目录

  4. iOS开发 沙盒路径和使用

    1.模拟器沙盒目录文件都在个人用户名文件夹下的一个隐藏文件夹里,中文叫资源库,他的目录其实是Library.因为应用是在沙箱(sandbox)中的,在文件读写权限上受到限制,只能在几个目录下读写文件: ...

  5. mysqld_safe启动报错 mysqld_safe The file /usr/local/mysql/bin/mysqld does not exist or is not executable

    报错(如下),但是使用mysqld直接启动没有问题. 150718 00:03:38 mysqld_safe Logging to '/var/log/mysqld.log'. 150718 00:0 ...

  6. [cocos2d-x]OPENGL ES支持的像素格式

    OPENGL ES最多支持32位颜色值. 支持的像素格式有以下几种: 客户端格式 GL格式 GL数据类型 字节数 RGBA8888 GL_RGBA GL_UNSIGNED_BYTE 4 RGB888 ...

  7. 学习PYTHON之路, DAY 2 - PYTHON 基础 2(基础数据类型)

    一 字符串格式化输出 name = 'nikita' age = 18 print ("I'am %s, age is %d") % (name, age) PS: 字符串是 %s ...

  8. JavaScript的Date对象

    整理了一些JavaScript时间的对象,如下所示: toLocaleString()得到当前的年月日和时间的字符串 toLocaleTimeString() 得到当前的时间字符串 toLocaleD ...

  9. 开发实时壁纸(Live Wallpapers)

    所谓实时壁纸,就是指手机桌面不再是简单的图片,而是运行中的动画,这个动画是由程序实时绘制的,因此被称为实时壁纸. 为了开发实时壁纸,Android提供了WallpaperService基类,实时壁纸的 ...

  10. 工厂方法(factory method)

    动机(Motivation) 在软件系统中,经常面临着“某个对象”的创建工作:由需求的变化,这个对象经常面临着剧烈的变化,但是它却拥有比较稳定的接口.如何应对这种变化?如何提供一种“封装机制”来隔离出 ...