题目链接:http://codeforces.com/problemset/problem/589/D
题目翻译:
迎接秋日的傍晚是沿着林荫大道散步的最佳时机,n个人决定这么做。
林荫大道可表示为轴线牛,每一个人都有三个参数来表征其行为:ti、si、fi——第i个人开始行走的时间时刻、行走的起点和终点。每个人沿着林荫大道从si到fi以1或- 1的恒定速度移动,这取决于方向。
当第i个人出现在林荫大道的一点,如果她立即开始走向点fi。
如果两个或两个以上的人在林荫大道上相遇(他们同时在同一地点,无论他们朝哪个方向走),他们都互相打招呼。就像在正常的生活中一样,每一对人都同时问候对方一次。
你的任务是为每个人计算她在大街上走的时候问候了多少人。
请注意,第i个人可能会在si和fi点与其他任何人见面和打招呼。当一个人到达目的地后,她就会走出林荫大道,不能和其他人打招呼。同样的规则也适用于散步的开始:一个人在出现在大街上之前不能和任何人打招呼。
输入
在第一行是一个整数n(2≤n≤1000)——的人数决定去散步。
下面的n行包含n个人的参数。在第i个行有三个正整数钛、硅、fi(1≤ti,si,fi≤106,如果≠fi),ti,si,fi -时间当第i个人的那一刻开始走路,走的开始点和结束点。
输出
输出的单行应该包含n个整数r1、r2、……, rn,间隔一个空间,其中ri表示第i个人沿着林荫大道散步时打招呼的数字。(来自有道翻译)
解题思路:建立直角坐标系,x轴为时间,y轴为位置,则可以构造函数y=k*x+b,根据所给的数据求出k,x的范围,b依次判断是否有交点即可,判断方法看代码中的注释吧。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000+5;
struct st
{
double k,b;
double t0,t1;//时间的取值范围
}stm[maxn];
int ans[maxn];
bool jug(st a,st b)//判断两个区间是否相交
{
if(a.t0>b.t1||a.t1<b.t0)
return false;
return true;
}
int main()
{
int n,i,j;
double t0,s0,s1,t;
double b2,b1;
memset(ans,0,sizeof(ans));
scanf("%d",&n);
for(i=0;i<n;i++)
{
cin>>t0>>s0>>s1;
if(s0<s1)
stm[i].k=1.0;
else
stm[i].k=-1.0;
stm[i].t0=t0;
stm[i].t1=stm[i].k*(s1-s0)+t0;
stm[i].b=s0-stm[i].k*t0;
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(stm[i].k==stm[j].k)
{
if(jug(stm[i],stm[j])&&stm[i].b==stm[j].b)//如果k相同且b相同,时间取值范围交叉,则这两个人相遇
{
ans[i]++;
ans[j]++;
}
}
else//k不相同的话则求出相遇的时间t若这个点在双方时间的取值范围内则这两个人相遇
{
b1=stm[i].k-stm[j].k;
b2=stm[j].b-stm[i].b;
t=b2/b1;
if(t>=stm[i].t0&&t<=stm[i].t1&&t>=stm[j].t0&&t<=stm[j].t1)
{
ans[i]++;
ans[j]++;
}
}
}
}
for(i=0;i<n;i++)
{
printf("%d ",ans[i]);
}
return 0;
}