[2016-03-20][UVALive][3905][Meteor]
Posted 红洋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[2016-03-20][UVALive][3905][Meteor]相关的知识,希望对你有一定的参考价值。
时间:2016-03-20 20:14:20 星期日
题目编号:[2016-03-20][UVALive][3905][Meteor]
题目大意:给定一定大小的相框,相框的右下角为坐标原点,给定n个星星的起始位置和运动方向,问相框内最多能捕捉到多少星星
方法:
- 把星星的运动方向分解成x和y两个方向,计算两个方向经过相框的时间,得到每个星星在相框的时间范围,题目就转换成,最多区间相交问题
计算时间:
- 计算直线上x为起点,a为增量,经过边界为w的时间对应的l和r
- 已知 0 < x + at < w —->得到是时间的范围
最多区间相加问题:
- 区间的左右端点记录成一个时间,按端点大小排序,遇到一个左端点,++cnt,遇到一个右端点–cnt,当遇到的左右端点值相同时,先处理右端点
小小优化:
- 计算时间的时候,0 < x + at < w 得到临界条件 t = (w-x)/a || t = -x/a 这里a为1~10的数字,只需要乘上lcm(1~10)=2520,就可以不用double类型了
//优化前
#include <algorithm>
#include <cstdio>
using namespace std;
#define FOR(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
const int maxn = 100000 + 10;
struct Event{
double x;
int type;
Event(){};
Event(double mX,int mType):x(mX),type(mType){}
bool operator < (const Event & a)const{
return x < a.x || (x == a.x && type > a.type);
}
}e[maxn * 2];
void update(int x,int a,int w,double &l,double &r){
if(a == 0){
//无解
if(x <= 0 || x >= w) r = l - 1;
}else if(a > 0){
l = max(l,-(double)x/a);
r = min(r,(double)(w - x)/a);
}else {
l = max(l,(double)(w - x)/a);
r = min(r,-(double)x/a);
}
}
int main(){
int t,w,h,n,x,y,a,b,cnt,ans,cur;
double l,r;
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&w,&h,&n);
cnt = 0;
FOR(i,0,n){
scanf("%d%d%d%d",&x,&y,&a,&b);
l = 0,r = 1E9;
update(x,a,w,l,r);
update(y,b,h,l,r);
if(r > l){
e[cnt++] = Event(l,0);
e[cnt++] = Event(r,1);
}
}
sort(e,e + cnt);
cur = 0,ans = 0;
FOR(i,0,cnt){
if(e[i].type) --cur;
else ans = max(++cur,ans);
}
printf("%d\n",ans);
}
return 0;
}
//优化后
#include <algorithm>
#include <cstdio>
using namespace std;
#define FOR(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
const int maxn = 100000 + 10;
struct Event{
int x,type;
Event(){};
Event(int mX,int mType):x(mX),type(mType){}
bool operator < (const Event & a)const{
return x < a.x || (x == a.x && type > a.type);
}
}e[maxn * 2];
void update(int x,int a,int w,int &l,int &r){
if(a == 0){
//无解
if(x <= 0 || x >= w) r = l - 1;
}else if(a > 0){
l = max(l,-x*2520/a);
r = min(r,(w - x)*2520/a);
}else {
l = max(l,(w - x)*2520/a);
r = min(r,-x*2520/a);
}
}
int main(){
int t,w,h,n,x,y,a,b,cnt,ans,cur,l,r;
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&w,&h,&n);
cnt = 0;
FOR(i,0,n){
scanf("%d%d%d%d",&x,&y,&a,&b);
l = 0,r = 1E9;
update(x,a,w,l,r);
update(y,b,h,l,r);
if(r > l){
e[cnt++] = Event(l,0);
e[cnt++] = Event(r,1);
}
}
sort(e,e + cnt);
cur = 0,ans = 0;
FOR(i,0,cnt){
if(e[i].type) --cur;
else ans = max(++cur,ans);
}
printf("%d\n",ans);
}
return 0;
}
以上是关于[2016-03-20][UVALive][3905][Meteor]的主要内容,如果未能解决你的问题,请参考以下文章