uvaoj1398/ LA3950

uvaoj1398


   题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4144

   学会了新的打点方式,特点类似时间轴,从前向后扫。

     细节注意 ,  如果 两个事件,前一个的结尾 等一后一个的开始,则算一个事件。



    

#include<cstdio>
#include<algorithm>
using namespace std;
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
#define INF 1<<30;
double l ,r ;  // L 开始进入的时间(必须是最大的,如只满足x到达界限内,而y没有那么,肯定没有进入区域内,所以最大的决定进入区域内) ,R结束出去的时间(必是最小的,同理,一个满足离开的,一定离开这个区域了)
typedef struct eve
{
	double e;
	int k;
}eve;
eve even[200005];
void update(int x ,int a ,int w)   //膜拜作者!!! 这个函数复用性很高!太巧妙了
{
	if(a == 0)
	{
		if( x<= 0 || x >= w ) r =l-1;   //巧妙的L,R,去除,有时去除不一定非要附一个特别的值,可以建立一种关系,是非常棒的想法
	}
	else if(a > 0 )  //排除了擦边的情况
	{
		l = max(l, -1.0*x/a);
		r = min(r,(w-x)*1.0/a);
	}
	else
	{
		l = max(l, (x-w)*-1.0/a );
		r = min(r, x*-1.0/a);
	}
	
	
}
		
int cmp(eve a ,eve b)
{
	return a.e < b.e || (a.e == b.e && a.k > b.k);

}

int main()
{

    int n,m,i,top,ans,cnt;
	int x,y,a,b;
	int w,h;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d %d",&w,&h);

		scanf("%d",&m);
		top = 0;
		for( i = 0 ;i<m ;i++)
		{		  
		  scanf("%d %d %d %d",&x,&y,&a,&b);
		  l = 0;r =INF;  
	          update(x,a,w);
		  update(y,b,h);  //L,R不断的精确,它受横纵坐标及速度的限制!
		  if(r - l > 1e-6)
		  {
		    even[top].e = l;
		    even[top].k = 0;
	//		printf("%f %d %d",even[top].e ,even[top].k ,top);
			top++;
		    even[top].e = r;
		    even[top].k = 1;
	//		printf("%f %d %d",even[top].e ,even[top].k ,top);
			top++;

		  }
		}


        sort(even,even+top ,cmp);


	
	

		ans = cnt = 0;
		for(i = 0;i<top;i++)
		{
			
			if(even[i].k == 0) 
			{
				cnt++;
				ans = max(ans ,cnt);
			}
			else cnt--;
		
		}

		printf("%d\n",ans);
	}
	return 0;
}








你可能感兴趣的:(ACM,uva,打点)