BZOJ4290 传送门
昨天考试考了这道题,学校评测不开O2被卡的一愣一愣的。
这种题线性复杂度就线性复杂度,为什么要卡常数。
顺便提一句,GRH大爷O(m*n*ans)的算法有90分,我的O(m*n)算法75。(万恶的STL)
这是什么烂数据(只是吐槽我们学校的数据,与BZOJ无关)
那我们来讲一讲做法:(首先,这是一道SB题)
我们考虑传送的行为:
1.如果一个传送门被穿越,那么从此以后进的那个门一定不用回去,出的那个门可以在出去以后立即打一枪替换。所以从此这两个门都不用进了
2.如果我们从一个传送门出来,那么我们一定有一个时刻枪可以打到传送门所在位置。
3.我们考虑这个位置:打完这一枪以后,在哪里开传送门并不重要,都可以到达。那么我们就贪心地走到最近的一面墙就可以了(这一步等价于建立一条从这个点到所有枪可以到达的点建立了一条长度为t+1的边(t为当前点到最近的贴墙空地的距离)
下面是代码:
/************************************************************** Problem: 4290 User: CYZ Language: C++ Result: Accepted Time:2444 ms Memory:81668 kb ****************************************************************/ #include<cstdio> #include<queue> #include<list> using namespace std ; const int MAXR = 1000 + 20 ; int C , R ; char M [ MAXR ] [ MAXR ] ; int dis1 [ MAXR ] [ MAXR ] ; int dis2 [ MAXR ] [ MAXR ] ; bool vis [ MAXR ] [ MAXR ] ; int s1 [ MAXR ] [ MAXR ] ; int s2 [ MAXR ] [ MAXR ] ; int s3 [ MAXR ] [ MAXR ] ; int s4 [ MAXR ] [ MAXR ] ; queue < pair < int , int > > q ; queue < pair < int , int > , list < pair < int , int > > > Q [ 1000 * 1000 + 20 ] ; int cx , cy ; int ans = -1 ; void P ( const int x , const int y ) { if ( x < 0 || x > C + 1 || y < 0 || y > R + 1 || dis1 [ x ] [ y ] != 0 ) return ; dis1 [ x ] [ y ] = 1 ; q . push ( make_pair ( x , y ) ) ; } template < class T1 , class T2 > void min_equal ( T1 & a , const T2 & b ) { if ( a > b ) a = b ; } template < class T1 , class T2 > void max_equal ( T1 & a , const T2 & b ) { if ( a < b ) a = b ; } int main () { /* freopen ( "portals.in" , "r" , stdin ) ; freopen ( "portals.out" , "w" , stdout ) ; */ scanf ( "%d%d" , & R , & C ) ; for ( int x = 1 ; x <= R ; ++ x ) scanf ( "%s" , M [ x ] + 1 ) ; for ( int x = 0 ; x <= R + 1 ; ++ x ) M [ x ] [ 0 ] = M [ x ] [ C + 1 ] = '#' ; for ( int y = 0 ; y <= C + 1 ; ++ y ) M [ 0 ] [ y ] = M [ R + 1 ] [ y ] = '#' ; for ( int x = 1 ; x <= R ; ++ x ) for ( int y = 1 ; y <= C ; ++ y ) { dis2 [ x ] [ y ] = 10000000 ; if ( M [ x ] [ y ] == 'S' ) { Q [ 0 ] . push ( make_pair ( x , y ) ) ; } else if ( M [ x ] [ y ] == 'C' ) { cx = x ; cy = y ; } } for ( int x = 0 ; x <= R + 1 ; ++ x ) for ( int y = 0 ; y <= C + 1 ; ++ y ) dis1 [ x ] [ y ] = M [ x ] [ y ] == '#' ; for ( int x = 0 ; x <= R + 1 ; ++ x ) for ( int y = 0 ; y <= C + 1 ; ++ y ) if ( M [ x ] [ y ] == '#' ) { P ( x + 1 , y ) ; P ( x - 1 , y ) ; P ( x , y - 1 ) ; P ( x , y + 1 ) ; } while ( ! q . empty () ) { const int x = q . front () . first ; const int y = q . front () . second ; q . pop () ; if ( dis1 [ x + 1 ] [ y ] == 0 ) { dis1 [ x + 1 ] [ y ] = dis1 [ x ] [ y ] + 1 ; q . push ( make_pair ( x + 1 , y ) ) ; } if ( dis1 [ x - 1 ] [ y ] == 0 ) { dis1 [ x - 1 ] [ y ] = dis1 [ x ] [ y ] + 1 ; q . push ( make_pair ( x - 1 , y ) ) ; } if ( dis1 [ x ] [ y + 1 ] == 0 ) { dis1 [ x ] [ y + 1 ] = dis1 [ x ] [ y ] + 1 ; q . push ( make_pair ( x , y + 1 ) ) ; } if ( dis1 [ x ] [ y - 1 ] == 0 ) { dis1 [ x ] [ y - 1 ] = dis1 [ x ] [ y ] + 1 ; q . push ( make_pair ( x , y - 1 ) ) ; } } for ( int x = 1 ; x <= R ; ++ x ) for ( int y = 1 ; y <= C ; ++ y ) { dis2 [ x ] [ y ] = -1 ; if ( s1 [ x ] [ y ] == 0 ) for ( int x2 = x ; M [ x2 ] [ y ] != '#' ; ++ x2 ) s1 [ x2 ] [ y ] = x ; if ( s3 [ x ] [ y ] == 0 ) for ( int y2 = y ; M [ x ] [ y2 ] != '#' ; ++ y2 ) s3 [ x ] [ y2 ] = y ; } for ( int x = R ; x >= 1 ; -- x ) for ( int y = C ; y >= 1 ; -- y ) { if ( s2 [ x ] [ y ] == 0 ) for ( int x2 = x ; M [ x2 ] [ y ] != '#' ; -- x2 ) s2 [ x2 ] [ y ] = x ; if ( s4 [ x ] [ y ] == 0 ) for ( int y2 = y ; M [ x ] [ y2 ] != '#' ; -- y2 ) s4 [ x ] [ y2 ] = y ; } for ( int t = 0 ; ans == -1 ; ++ t ) { queue < pair < int , int > , list < pair < int , int > > > & q = Q [ t ] ; while ( ! q . empty () ) { const int x = q . front () . first ; const int y = q . front () . second ; q . pop () ; if ( vis [ x ] [ y ] ) continue ; vis [ x ] [ y ] = true ; dis2 [ x ] [ y ] = t ; if ( x == cx && y == cy ) { ans = t ; break ; } if ( M [ x + 1 ] [ y ] != '#' && ! vis [ x + 1 ] [ y ] ) Q [ t + 1 ] . push ( make_pair ( x + 1 , y ) ) ; if ( M [ x - 1 ] [ y ] != '#' && ! vis [ x - 1 ] [ y ] ) Q [ t + 1 ] . push ( make_pair ( x - 1 , y ) ) ; if ( M [ x ] [ y + 1 ] != '#' && ! vis [ x ] [ y + 1 ] ) Q [ t + 1 ] . push ( make_pair ( x , y + 1 ) ) ; if ( M [ x ] [ y - 1 ] != '#' && ! vis [ x ] [ y - 1 ] ) Q [ t + 1 ] . push ( make_pair ( x , y - 1 ) ) ; if ( ! vis [ s1 [ x ] [ y ] ] [ y ] ) Q [ t + dis1 [ x ] [ y ] ] . push ( make_pair ( s1 [ x ] [ y ] , y ) ) ; if ( ! vis [ s2 [ x ] [ y ] ] [ y ] ) Q [ t + dis1 [ x ] [ y ] ] . push ( make_pair ( s2 [ x ] [ y ] , y ) ) ; if ( ! vis [ x ] [ s3 [ x ] [ y ] ] ) Q [ t + dis1 [ x ] [ y ] ] . push ( make_pair ( x , s3 [ x ] [ y ] ) ) ; Q [ t + dis1 [ x ] [ y ] ] . push ( make_pair ( x , s4 [ x ] [ y ] ) ) ; } } /* for ( int x = 1 ; x <= R ; ++ x ) { for ( int y = 1 ; y <= C ; ++ y ) printf ( "%2d " , dis2 [ x ] [ y ] ) ; putchar ( '\n' ) ; }*/ printf ( "%d\n" , ans ) ; return 0 ; }