题目大意:

  给定一个网格,已知光线的起始位置和方向,以及障碍物的位置,光线遇到边界或障碍物都会反弹,求光线能通过几个格子。

题解:

  这是一道模拟题。

  60%数据(n,m<=1000)

    直接n2模拟,用x,y,z记录光线的位置及方向,用二维数组记录地图状况,不断移动直至回到起点(方向与出发时一致),把路径上的点都打上标记,最后统计标记的数量即可。

    复杂度O(nm)。

    其实模拟有几个小技巧:

    1、开始时可以将地图边缘都存成障碍物,可省去不少判断;

    2、宏定义数组{1,1,-1,-1},{1,-1,1,-1}代表方向;

    3、模拟时只打标记,最后统计答案。

  100%数据(n,m<=100000)

    n2显然受不了,我们需要想办法将程序优化到nlogn。

    n,m大小的数组开不下,我们可以用STL的vector存储障碍的位置,和上面一样,地图边界也视为障碍物。假设(1,1)在左上角,则对于每条左上——右下的直线,其上的点横坐标与纵坐标的差相等,右上——左下的直线,其上的点横纵坐标之和相等,我们可以利用此性质给直线标号。每条直线所对应的vector里只用存横坐标,纵坐标可以算出。

    将每个障碍物存进vector里以后,sort一下,然后我们可以利用二分求出某个方向上最近的障碍物,在vector里二分查找,复杂度为logn,可以接受。

    我们在模拟时,可以将模拟加速,就是每次跳到一条直线的尽头,然后改变方向,直至回到起点。此时不能再打标记,只能将路径长度相加。值得注意的是,如果在行进过程中反向,则每个格子都会被重复经过两次,应将总答案除以2。

    我们依然用三个数x,y,z表示位置及方向,每次行进时,先利用二分找到最近的障碍物,然或利用二分判断周边有没有其他可能影响路径的障碍物。二分查找相邻的直线,判断求得的位置是否与障碍物相邻即可。此时便可以用到临边标号相差一的性质。

    最后注意回到起点的判断,不仅要判断是否共线或同向,也要判断他们的相对位置,以及之间有没有障碍物。

    复杂度O(nlogn)。

Code:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<string>
  4 #include<cstring>
  5 #include<vector>
  6 #include<algorithm>
  7 #define LL long long
  8 using namespace std;
  9 const int N=1000010;
 10 int n,m,k,sx,sy,dir,d0,nowa,nowb,nxta,nxtb,flag;
 11 string str;
 12 vector<int> v[5][N<<1];
 13 void add(int x,int y)
 14 {
 15     v[1][x-y+N].push_back(x);
 16     v[2][x+y].push_back(x);
 17     v[3][x-y+N].push_back(x);
 18     v[4][x+y].push_back(x);
 19 }
 20 int bound(int x,int y,int z,int val)
 21 {
 22     int ans=-1;
 23     if(z==1){
 24         int l=0,r=v[x][y].size()-1;
 25         while(l<=r){
 26             int mid=(l+r)>>1;
 27             if(v[x][y][mid]>val){
 28                 r=mid-1;
 29                 ans=mid;
 30             }
 31             else l=mid+1;
 32         }
 33     }
 34     else{
 35         int l=0,r=v[x][y].size()-1;
 36         while(l<=r){
 37             int mid=(l+r)>>1;
 38             if(v[x][y][mid]<val){
 39                 l=mid+1;
 40                 ans=mid;
 41             }
 42             else r=mid-1;
 43         }
 44     }
 45     return v[x][y][ans];
 46 }
 47 int main()
 48 {
 49     cin>>n>>m>>k;
 50     for(int i=1;i<=k;i++){
 51         int x,y;
 52         scanf("%d%d",&x,&y);
 53         add(x,y);
 54     }
 55     cin>>sx>>sy;
 56     cin>>str;
 57     if(str[0]=='S'){
 58         if(str[1]=='E') dir=1;
 59         else dir=4;
 60     }
 61     else{
 62         if(str[1]=='E') dir=2;
 63         else dir=3;
 64     }
 65     for(int i=0;i<=n+1;i++){
 66         add(i,0);add(i,m+1);    
 67     }
 68     for(int i=1;i<=m;i++){
 69         add(0,i);add(n+1,i);    
 70     }
 71     for(int i=0;i<=2*N-1;i++){
 72         sort(v[1][i].begin(),v[1][i].end());
 73         sort(v[2][i].begin(),v[2][i].end());
 74         sort(v[3][i].begin(),v[3][i].end());
 75         sort(v[4][i].begin(),v[4][i].end());
 76     }
 77     LL ans=0;int flag=0;
 78     d0=dir;nowa=sx;nowb=sy;
 79     while(1){
 80         if(dir==1){
 81             nxta=bound(1,nowa-nowb+N,1,nowa)-1;
 82             nxtb=nxta-nowa+nowb;ans+=(LL)(nxta-nowa+1);
 83             int a=bound(1,nowa-nowb+N+1,1,nxta),b=bound(1,nowa-nowb+N-1,1,nxta-1);
 84             if(a==nxta+1&&b==nxta){
 85                 flag=1;dir=3;
 86                 nowa=nxta;nowb=nxtb;
 87             }
 88             else if(a==nxta+1){                            
 89                 dir=2;
 90                 nowa=nxta;nowb=nxtb+1;
 91             }
 92             else if(b==nxta){
 93                 dir=4;
 94                 nowb=nxtb;nowa=nxta+1;
 95             }
 96             else{
 97                 flag=1;dir=3;
 98                 nowa=nxta;nowb=nxtb;
 99             }
100         }
101         else if(dir==2){
102             nxta=bound(2,nowa+nowb,2,nowa)+1;
103             nxtb=nowa+nowb-nxta;ans+=(LL)(nowa-nxta+1);
104             int a=bound(2,nowa+nowb-1,2,nxta),b=bound(2,nowa+nowb+1,2,nxta+1);
105             if(a==nxta-1&&b==nxta){
106                 flag=1;dir=4;
107                 nowa=nxta;nowb=nxtb;
108             } 
109             else if(a==nxta-1){                            
110                 dir=1;
111                 nowa=nxta;nowb=nxtb+1;
112             }
113             else if(b==nxta){
114                 dir=3;
115                 nowb=nxtb;nowa=nxta-1;
116             }
117             else{
118                 flag=1;dir=4;
119                 nowa=nxta;nowb=nxtb;
120             }
121         }
122         else if(dir==3){
123             nxta=bound(3,nowa-nowb+N,2,nowa)+1;
124             nxtb=nxta-nowa+nowb;ans+=(LL)(nowa-nxta+1);
125             int a=bound(3,nowa-nowb+N-1,2,nxta),b=bound(3,nowa-nowb+N+1,2,nxta+1);
126             if(a==nxta-1&&b==nxta){
127                 flag=1;dir=1;
128                 nowa=nxta;nowb=nxtb;
129             } 
130             else if(a==nxta-1){                            
131                 dir=4;
132                 nowa=nxta;nowb=nxtb-1;
133             }
134             else if(b==nxta){
135                 dir=2;
136                 nowb=nxtb;nowa=nxta-1;
137             }
138             else{
139                 flag=1;dir=1;
140                 nowa=nxta;nowb=nxtb;
141             }
142         }
143         else{
144             nxta=bound(4,nowa+nowb,1,nowa)-1;
145             nxtb=nowa+nowb-nxta;ans+=(LL)(nxta-nowa+1);
146             int a=bound(4,nowa+nowb+1,1,nxta),b=bound(4,nowa+nowb-1,1,nxta-1);
147             if(a==nxta+1&&b==nxta){
148                 flag=1;dir=2;
149                 nowa=nxta;nowb=nxtb;
150             } 
151             else if(a==nxta+1){                            
152                 dir=3;
153                 nowa=nxta;nowb=nxtb-1;
154             }
155             else if(b==nxta){
156                 dir=1;
157                 nowb=nxtb;nowa=nxta+1;
158             }
159             else{
160                 flag=1;dir=2;
161                 nowa=nxta;nowb=nxtb;
162             }
163         }
164         if(dir==d0){
165             if(dir==1){
166                 int nxt=bound(1,nowa-nowb+N,1,nowa);
167                 if(nowa-nowb==sx-sy&&sx>=nowa&&sx<nxt){
168                     ans+=(LL)(sx-nowa);break;
169                 }            
170             }
171             else if(dir==2){
172                 int nxt=bound(2,nowa+nowb,2,nowa);
173                 if(nowa+nowb==sx+sy&&sx<=nowa&&sx>nxt){
174                     ans+=(LL)(nowa-sx);break;
175                 }
176             }
177             else if(dir==3){
178                 int nxt=bound(3,nowa-nowb+N,2,nowa);
179                 if(nowa-nowb==sx-sy&&sx<=nowa&&sx>nxt){
180                     ans+=(LL)(nowa-sx);break;                
181                 }
182             }
183             else{
184                 int nxt=bound(4,nowa+nowb,1,nowa);
185                 if(nowa+nowb==sx+sy&&sx>=nowa&&sx<nxt){
186                     ans+=(LL)(sx-nowa);break;
187                 }
188             }
189         }
190     }
191     if(flag==1)    ans/=2;
192     cout<<ans<<endl;
193     return 0;
194 }
View Code

猜你喜欢

转载自www.cnblogs.com/hz-Rockstar/p/11234695.html