2018/07/23测试T2 Route(数论)

【题目】

题目描述:

一条直线上有 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;
}

猜你喜欢

转载自blog.csdn.net/forever_dreams/article/details/81168984