時間: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;}