【题目】
题目描述:
一条直线上有 n 个人在走,有三个值来描述第 i 个人的行为:t[i],s[i],f[i],分别表示他出发的时间,他的起点位置和终点位置。假设每个人走的一样快,他们每个单位时间只会朝目的地走一个单位的距离。
当两个人相遇的时候,他们相互之间会打招呼。按照常理,两个人之间最多只会打一次招呼。
请算出每个人在他的旅程中要和多少个人打招呼。
注意:
(1)某个人在出发前是不在直线上的;
(2)到终点后,这个人也不再出现在直线上;
(3)如果 2 个人在同一个位置、同一时刻出发,属于相遇的情况。
输入格式:
输入第一行包括一个整数 n 表示人数。
接下来 n 行,每行三个整数 t[i],s[i],f[i]。
输出格式:
一行 n 个整数。第 i 个整数 a[i] 表示第 i 个人总共要和 a[i] 个人(总人数)打招呼。
样例数据 :
输入
3
1 1 10
5 8 2
9 9 10输出
2 1 1
备注:
样例说明:
数据范围:
对 30% 的输入数据 :n ≤ 10
对 100% 的输入数据 :n ≤ 1000,1≤ t[i],s[i],f[i] ≤ 1000000,s[i] ≠ f[i]
【分析】
这道题……暴力得了30分
后来听大佬讲才知道这是一道小学奥数相遇问题Orz
具体的操作细节就看代码吧
我相信大家都会小学奥数的
【代码】
附上正解的代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1005
using namespace std;
int t[N],s[N],f[N];
int main() {
// freopen("route.in","r",stdin);
// freopen("route.out","w",stdout);
int n,i,j,l,r,ans;
scanf("%d",&n);
for(i=1;i<=n;++i)
scanf("%d%d%d",&t[i],&s[i],&f[i]);
for(i=1;i<=n;++i)
{
ans=0;
for(j=1;j<=n;++j)
{
if(i==j) continue;
if(s[i]<f[i]&&s[j]<f[j])
{
l=max(s[i],s[j]);
r=min(f[i],f[j]);
if(l>r) continue;
if(l-s[i]+t[i]==l-s[j]+t[j]) ans++;
}
else if(s[i]>f[i]&&s[j]>f[j])
{
l=min(s[i],s[j]);
r=max(f[i],f[j]);
if(l<r) continue;
if(s[i]-l+t[i]==s[j]-l+t[j]) ans++;
}
else
{
int si,fj,ti,tj;
if(s[i]<f[i])
{
si=s[i];
ti=t[i];
fj=s[j];
tj=t[j];
l=max(s[i],f[j]);
r=min(f[i],s[j]);
}
else
{
si=s[j];
ti=t[j];
fj=s[i];
tj=t[i];
l=max(s[j],f[i]);
r=min(f[j],s[i]);
}
if(l>r) continue;
if(-ti+tj+si+fj<0) continue;
int x=(-ti+tj+si+fj);
if(x>=2*l&&x<=2*r) ans++;
}
}
printf("%d ",ans);
}
// fclose(stdin);
// fclose(stdout);
return 0;
}