BZOJ-1499: [NOI2005]瑰丽华尔兹(DP+单调队列优化)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1499

可以很容易的写出DP方程f[t][i][j]=max(f[t-1][i][j],f[t-1][last(i)][last(j)]+1),但是这个DP的总复杂度是O(nmT),会TLE,所以不用时间来划分状态,而是使用时段来划分状态,h表示第h个时间段,那么f[h][i][j]=max(f[h-1][last(i)][last(j)]+dist(i,j,last(i),last(j))),这个方程直接转移状态是O(n),但是我们可以使用单调队列优化维护决策到O(1),那么DP复杂度就成了O(nmk),可以AC。

代码:

#include 

#include 

#include 

#include 

 

using namespace std ;

 

#define MAXN 210

#define MAXK 210

#define rep( i , x )for(int i =0; i ++< x ;)

#define dow( i , x )for(int i = x ; i ;-- i )

 

char map[ MAXN ][ MAXN ];

int f[ MAXN ][ MAXN ][ MAXN ], n , m , k , x , y ;

 

deque  Q ;

 

int main(  ){

    scanf("%d%d%d%d%d",&n ,&m ,&x ,&y ,&k );

    rep( i , n )scanf("%s", map[ i ]+1);

    rep( i , n )rep( j , m ) f[0][ i ][ j ]=-1;

    f[0][ x ][ y ]=0;

    rep( h , k ){

        int l , r , d ;scanf("%d%d%d",&l ,&r ,&d );

        rep( i , n )rep( j , m ) f[ h ][ i ][ j ]=-1;

        if( d ==1){

            rep( j , m ){

                Q.clear(  );

                dow( i , n )if( map[ i ][ j ]=='.'){

                    while(! Q.empty(  )&& Q.front(  )- i > r - l +1) Q.pop_front(  );

                    if( f[ h -1][ i ][ j ]!=-1){

                        while(! Q.empty(  )&& Q.back(  )- i + f[ h -1][ Q.back(  )][ j ]<= f[ h -1][ i ][ j ]) Q.pop_back(  );

                        Q.push_back( i );

                    }

                    if(! Q.empty(  )) f[ h ][ i ][ j ]= f[ h -1][ Q.front(  )][ j ]+ Q.front(  )- i ;

                    else f[ h ][ i ][ j ]=-1;

                }else{

                    Q.clear(  ); f[ h ][ i ][ j ]=-1;

                }

            }

        }else if( d ==2){

            rep( j , m ){

                Q.clear(  );

                rep( i , n )if( map[ i ][ j ]=='.'){

                    while(! Q.empty(  )&& i - Q.front(  )> r - l +1) Q.pop_front(  );

                    if( f[ h -1][ i ][ j ]!=-1){

                        while(! Q.empty(  )&& i - Q.back(  )+ f[ h -1][ Q.back(  )][ j ]<= f[ h -1][ i ][ j ]) Q.pop_back(  );

                        Q.push_back( i );

                    }

                    if(! Q.empty(  )) f[ h ][ i ][ j ]= f[ h -1][ Q.front(  )][ j ]+ i - Q.front(  );

                    else f[ h ][ i ][ j ]=-1;

                }else{

                    Q.clear(  ); f[ h ][ i ][ j ]=-1;

                }

            }

        }else if( d ==3){

            rep( i , n ){

                Q.clear(  );

                dow( j , m )if( map[ i ][ j ]=='.'){

                    while(! Q.empty(  )&& Q.front(  )- j > r - l +1) Q.pop_front(  );

                    if( f[ h -1][ i ][ j ]!=-1){

                        while(! Q.empty(  )&& Q.back(  )- j + f[ h -1][ i ][ Q.back(  )]<= f[ h -1][ i ][ j ]) Q.pop_back(  );

                        Q.push_back( j );

                    }

                    if(! Q.empty(  )) f[ h ][ i ][ j ]= Q.front(  )- j + f[ h -1][ i ][ Q.front(  )];

                    else f[ h ][ i ][ j ]=-1;

                }else{

                    Q.clear(  ); f[ h ][ i ][ j ]=-1;

                }

            }

        }else{

            rep( i , n ){

                Q.clear(  );

                rep( j , m )if( map[ i ][ j ]=='.'){

                    while(! Q.empty(  )&& j - Q.front(  )> r - l +1) Q.pop_front(  );

                    if( f[ h -1][ i ][ j ]!=-1){

                        while(! Q.empty(  )&& j - Q.back(  )+ f[ h -1][ i ][ Q.back(  )]<= f[ h -1][ i ][ j ]) Q.pop_back(  );

                        Q.push_back( j );

                    }

                    if(! Q.empty(  )) f[ h ][ i ][ j ]= j - Q.front(  )+ f[ h -1][ i ][ Q.front(  )];

                    else f[ h ][ i ][ j ]=-1;

                }else{

                    Q.clear(  ); f[ h ][ i ][ j ]=-1;

                }

            }

        }

    }

    int ans =0;

    rep( i , n )rep( j , m ) ans =max( ans , f[ k ][ i ][ j ]);

    printf("%d\n", ans );

    return 0;

}

你可能感兴趣的:(BZOJ-1499: [NOI2005]瑰丽华尔兹(DP+单调队列优化))