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

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

题目

在这里插入图片描述

题解

题意

n n 个人,每个人的速度都为1
有些人的方向为向右,有些向左
i i 个人在第 t [ i ] t[i] 秒的时候在 s [ i ] s[i] 这个位置出现,在第 f [ i ] f[i] 这个位置消失
如果两个人在某一时间同时在同一地点,那么认为这两个相遇
求出每个人会与其他人相遇多少次

分析

首先先求出方向,用1/-1表示
那么对于两个方向不同的人,设在第 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]
解释:
i i j j 表示两个人,数组 s s ,数组 t t 如题,数组 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 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]|)
对于两个方向不同的人,由于速度一样,所以要想相遇,就要在时间差内两个人要到同一 位置
略微推一下就有 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) 模拟

Code

#include<cstdio>
#include<cmath>
#include<iostream>
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;
}

猜你喜欢

转载自blog.csdn.net/LZX_lzx/article/details/107620563
今日推荐