有 n n n个人,每个人的速度都为1
有些人的方向为向右,有些向左
第 i i i个人在第 t [ i ] t[i] t[i]秒的时候在 s [ i ] s[i] s[i]这个位置出现,在第 f [ i ] f[i] f[i]这个位置消失
如果两个人在某一时间同时在同一地点,那么认为这两个相遇
求出每个人会与其他人相遇多少次
首先先求出方向,用1/-1表示
那么对于两个方向不同的人,设在第 x x x秒的时候两人相遇
有方程:
s [ i ] + ( x − t [ i ] ) ∗ b [ i ] = s [ j ] + ( x − t [ j ] ) ∗ b [ j ] s[i]+(x-t[i])*b[i]=s[j]+(x-t[j])*b[j] s[i]+(x−t[i])∗b[i]=s[j]+(x−t[j])∗b[j]
解释:
i i i和 j j j表示两个人,数组 s s s,数组 t t t如题,数组 b b b表示上面说到的方向(下面同理),即1/-1
解方程得
x = s [ j ] − s [ i ] + b [ i ] ∗ t [ i ] − b [ j ] ∗ t [ j ] b [ i ] − b [ j ] x=\dfrac{s[j]-s[i]+b[i]*t[i]-b[j]*t[j]}{b[i]-b[j]} x=b[i]−b[j]s[j]−s[i]+b[i]∗t[i]−b[j]∗t[j]
代入可求出 x x x
那么显而易见,当 x x x合法时,两人会相遇
合法范围:
m a x ( t [ i ] , t [ j ] ) ≤ x ≤ m i n ( t [ i ] + ∣ s [ i ] − f [ i ] ∣ , t [ j ] + ∣ s [ j ] − f [ j ] ∣ ) max(t[i],t[j])≤x≤min(t[i]+|s[i]-f[i]|,t[j]+|s[j]-f[j]|) max(t[i],t[j])≤x≤min(t[i]+∣s[i]−f[i]∣,t[j]+∣s[j]−f[j]∣)
对于两个方向不同的人,由于速度一样,所以要想相遇,就要在时间差内两个人要到同一 位置
略微推一下就有 s [ i ] + t [ j ] ∗ b [ i ] = s [ j ] + t [ i ] ∗ b [ j ] s[i]+t[j]*b[i]=s[j]+t[i]*b[j] s[i]+t[j]∗b[i]=s[j]+t[i]∗b[j]
当上面这个式子成立时,两人相遇
注意细节
O ( n 2 ) O(n^2) O(n2)模拟
#include
#include
#include
using namespace std;
int n,i,j,x,y,c,c1,c2,cx,cy,ans,t[1005],s[1005],f[1005],b[1005];
double tt;
int main()
{
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
scanf("%d",&n);
for (i=1;i<=n;i++)
{
scanf("%d%d%d",&t[i],&s[i],&f[i]);
if (s[i]<f[i]) b[i]=1;
else b[i]=-1;
}
for (i=1;i<=n;i++)
{
ans=0;
for (j=1;j<=n;j++)
{
c=c1=c2=cx=cy=0;
tt=0;
if (i!=j)
{
c=abs(t[i]-t[j]);
c1=abs(f[i]-s[i]);
c2=abs(f[j]-s[j]);
x=s[i];
y=s[j];
if (t[i]<=t[j])
{
x+=b[i]*(t[j]-t[i]);
cx=c;
cy=0;
}
else
{
y+=b[j]*(t[i]-t[j]);
cy=c;
cx=0;
}
if (b[i]==b[j])
{
if (x==y&&cx<=c1&&cy<=c2) ans++;
}
else
{
tt=1.0*(y-x)/((b[i]-b[j]));
if (tt<0) continue;
if (cx+tt<=c1&&cy+tt<=c2) ans++;
}
}
}
printf("%d ",ans);
}
fclose(stdin);
fclose(stdout);
return 0;
}