CodeForces - 589D

题目链接:http://codeforces.com/problemset/problem/589/D

题目翻译:

迎接秋日的傍晚是沿着林荫大道散步的最佳时机,n个人决定这么做。
林荫大道可表示为轴线牛,每一个人都有三个参数来表征其行为:ti、si、fi——第i个人开始行走的时间时刻、行走的起点和终点。每个人沿着林荫大道从si到fi以1或- 1的恒定速度移动,这取决于方向。
当第i个人出现在林荫大道的一点,如果她立即开始走向点fi。
如果两个或两个以上的人在林荫大道上相遇(他们同时在同一地点,无论他们朝哪个方向走),他们都互相打招呼。就像在正常的生活中一样,每一对人都同时问候对方一次。
你的任务是为每个人计算她在大街上走的时候问候了多少人。
请注意,第i个人可能会在si和fi点与其他任何人见面和打招呼。当一个人到达目的地后,她就会走出林荫大道,不能和其他人打招呼。同样的规则也适用于散步的开始:一个人在出现在大街上之前不能和任何人打招呼。
输入
在第一行是一个整数n(2≤n≤1000)——的人数决定去散步。
下面的n行包含n个人的参数。在第i个行有三个正整数钛、硅、fi(1≤ti,si,fi≤106,如果≠fi),ti,si,fi -时间当第i个人的那一刻开始走路,走的开始点和结束点。
输出
输出的单行应该包含n个整数r1、r2、……, rn,间隔一个空间,其中ri表示第i个人沿着林荫大道散步时打招呼的数字。(来自有道翻译)

解题思路:建立直角坐标系,x轴为时间,y轴为位置,则可以构造函数y=k*x+b,根据所给的数据求出k,x的范围,b依次判断是否有交点即可,判断方法看代码中的注释吧。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000+5;
struct st
{
	double k,b;
	double t0,t1;//时间的取值范围
}stm[maxn];
int ans[maxn];
bool jug(st a,st b)//判断两个区间是否相交
{
	if(a.t0>b.t1||a.t1<b.t0)
	return false;
	return true;
}
int main()
{
	int n,i,j;
	double t0,s0,s1,t;
	double b2,b1;
	memset(ans,0,sizeof(ans));
	scanf("%d",&n);
	for(i=0;i<n;i++)
	{
		cin>>t0>>s0>>s1;
		if(s0<s1)
		stm[i].k=1.0;
		else
		stm[i].k=-1.0;
		stm[i].t0=t0;
		stm[i].t1=stm[i].k*(s1-s0)+t0;
		stm[i].b=s0-stm[i].k*t0;
	}
	for(i=0;i<n;i++)
	{
		for(j=i+1;j<n;j++)
		{
			if(stm[i].k==stm[j].k)
			{
				if(jug(stm[i],stm[j])&&stm[i].b==stm[j].b)//如果k相同且b相同,时间取值范围交叉,则这两个人相遇
				{
					ans[i]++;
					ans[j]++;
				}
			}
			else//k不相同的话则求出相遇的时间t若这个点在双方时间的取值范围内则这两个人相遇
			{
				b1=stm[i].k-stm[j].k;
				b2=stm[j].b-stm[i].b;
				t=b2/b1;
				if(t>=stm[i].t0&&t<=stm[i].t1&&t>=stm[j].t0&&t<=stm[j].t1)
				{
					ans[i]++;
					ans[j]++;
				}
			}
		}
	}
	for(i=0;i<n;i++)
	{
		printf("%d ",ans[i]);
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值