【2017杭二联考】穿越矩形

P2554 - 【2017杭二联考】穿越矩形

Description

题目背景: 
幻想乡的创始人之一,八云紫,有着强大的控制结界的能力,可以瞬间消除一定范围内 所有弹幕。我们可以将其消除范围视为一个矩形,而弹幕可以视为动点。 
八云紫想要嘲讽她的敌人,所以她希望只使用一次消除能力,尽可能多地消除弹幕。 
请你告诉她,在哪一时刻使用道具,可以消除尽可能多的弹幕。

问题描述: 
在平面上给定一个矩形区域(也可能退化成线段或者点)。 矩形的边与坐标轴平行,左下端 点为 (xl,yl),右上端点为 (xr,yr)。 
给定 n 个动点,初始坐标为 (xi, yi),运动方向为 (ui,vi),速度为 sqrt((ui)2+(vi)2)sqrt((ui)2+(vi)2) 求在哪一时刻 t ( t ∈N ),在矩形内部及边界的动点数目最多。 
如果有多个 t 满足条件,输出最小的 t 即可。

Input

第一行 5 个正整数,n, xl, yl, xr, yr,表示动点个数和矩形区域。 
接下来 n 行,每行 4 个整数,xi, yi, ui, vi ,描述第 i 个动点。

Output

在矩形内部及边界的动点数目最多的时刻 t ( t ∈N )。 
如果有多个 t 满足条件,输出最小的 t 即可。

Sample Input

2 2 2 3 3 
3 1 -1 1 
2 3 1 -1

Sample Output

1

Hint

数据范围: 
对于前 40% 数据, 1<= n <= 100, 1 <= xl, xr, yl, yr, xi, yi <= 100, -10 <= ui, vi <= 10 
对于 100% 数据,1<= n <= 10^5, 1 <= xl, xr, yl, yr, xi, yi <= 10^9, 0 <= |ui|, |vi|<= 10^5, xl <= xr, yl <= yr 
保证 n,xl,xr,yl,yr,xi,yi,ui,vi 均为整数.

Source

数学,计算几何

 

考试时看错题目了,以为方向指的是从原点向给出的 (ui,vi)走(我以为是一个坐标),然后就GG了。。。

首先明确(ui,vi)是一个向量,由于速度是sqrt((ui)2+(vi)2)sqrt((ui)2+(vi)2),向量分解一下就是横坐标+u,纵坐标+v,然后模拟每一秒的运动情况,再判断,就可获得40分。(详见work()函数)

一百分的做法呢?我们发现其实只要知道在哪一个时间段内点在矩形上或中就可以了。我们预处理出每个点在矩形内部的时间(用临界点计算),再将时间离散化,将每个点的时间差分,最后o(n)取最大即可。

交了一发WA了,90分,不知道错了哪里。。。发现是小数据WA了,就可耻的加了个work()暴力程序去算。。。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<stack>
 9 #include<queue>
10 #include<map>
11 #define RG register
12 #define IL inline
13 #define pi acos(-1.0)
14 #define ll long long 
15 using namespace std;
16 struct point{
17   int x,y,u,v;
18 };
19 point a[100005];
20 int n,xl,yl,xr,yr,cnt=0;
21 int in[100005],out[100005];
22 int l[100005],r[100005];
23 int F[200005],rak[200005];
24 int c[200005];
25 map <int,int> s;
26 void work(){
27   int T=0,cnt=0,maxn=0;
28   for(int t=1;   ;t++){
29      int ans=0;
30      for(int j=1;j<=n;j++){
31        a[j].x+=a[j].u;
32        a[j].y+=a[j].v;//分解向量
33        ++cnt;
34        if(a[j].x>=xl&&a[j].x<=xr&& a[j].y>=yl&& a[j].y<=yr)  ++ans;
35        if(cnt>=10000000){
36         printf("%d",T);
37         exit(0);
38         }
39      }
40      if(ans>maxn)  maxn=ans,T=t;
41      if(cnt>=10000000){
42      printf("%d",T);
43      exit(0);
44      }
45   }
46 }
47 int main() {
48   scanf("%d%d%d%d%d",&n,&xl,&yl,&xr,&yr);
49   for(int i=1;i<=n;i++)  scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].u,&a[i].v);
50   if(n<=100) work();
51   for(int i=1;i<=n;i++){
52     int txl,txr,tyl,tyr;
53     if((a[i].u==0)&&(a[i].x<xl||a[i].x>xr)) continue;
54     if((a[i].v==0)&&(a[i].y<yl||a[i].y>yr)) continue;//不可能成立直接判断掉
55     if(a[i].u==0) txl=0,txr=999999999;
56     else{
57        txl=(xl-a[i].x)%a[i].u==0?(xl-a[i].x)/a[i].u:(xl-a[i].x-1)/a[i].u+1;
58        txr=(xr-a[i].x)/a[i].u;
59        if(a[i].u<0) swap(txl,txr);
60     }
61     if(a[i].v==0) tyl=0,tyr=999999999;
62     else{
63        tyl=(yl-a[i].y)%a[i].v==0?(yl-a[i].y)/a[i].v:(yl-a[i].y-1)/a[i].v+1;
64        tyr=(yr-a[i].y)/a[i].v;
65        if(a[i].v<0) swap(tyl,tyr);
66     }
67     if(txl<0) txl=0; if(txr<0) txr=-1;
68     if(tyl<0) tyl=0; if(tyr<0) tyr=-1;
69     int L=max(txl,tyl),R=min(txr,tyr);
70     if(L>R) continue;
71     ++cnt;
72     l[cnt]=L,r[cnt]=R;
73   }
74   for(int i=1;i<=cnt;i++)  F[++F[0]]=l[i],F[++F[0]]=r[i];
75   sort(F+1,F+F[0]+1);
76   int tep=0;
77   for(int i=1;i<=F[0];i++)
78       if(i==1||F[i]!=F[i-1]) s[F[i]]=++tep,rak[tep]=F[i];
79   for(int i=1;i<=cnt;i++){
80       c[s[l[i]]]++;
81       c[s[r[i]]+1]--;
82   }
83   int maxn=0,T=0,j=0;
84   for(int i=1;i<=tep;i++){
85       j+=c[i];
86       if(j>maxn)  maxn=j,T=i;
87   }
88   printf("%d",rak[T]);
89   return 0;
90 }

 

posted @ 2017-08-22 00:05  nfy_algorithm  阅读(230)  评论(0编辑  收藏  举报