【NOIP2015模拟10.30晚】JZOJ7月27日提高组T2 走路

【NOIP2015模拟10.30晚】JZOJ7月27提高组T2 走路

  • 题目
  • 题解
    • 题意
    • 分析
    • Code

题目

【NOIP2015模拟10.30晚】JZOJ7月27日提高组T2 走路_第1张图片

题解

题意

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]+(xt[i])b[i]=s[j]+(xt[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])xmin(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)模拟

Code

#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;
}

你可能感兴趣的:(信息学总结)