您的位置:首页 > 其它

uvaoj1398/ LA3950

2016-05-05 23:38 330 查看
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;
}











内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: