zstu3924 [NOI2005]瑰丽华尔兹 (单调队列dp)

来源:互联网 发布:sybase数据库日志查看 编辑:程序博客网 时间:2024/05/17 07:49

zstu3924 [NOI2005]瑰丽华尔兹 (单调队列dp)

题意:中文不解释。。

解题思路:先列出dp状态,dp[i][j][k]表示在k时刻,停留在(i,j)位置时,能走的最长的路程。但是我后来在网上查了下数据范围,i,j<=200,k<=40000这样直接做是会超时,超内存的,那么用单调队列优化下。用dp[i][j][k]表示在第k个时间段,在(i,j)位置时,能走的最长路程,注意,这里的k表示的是时间段了,而不是时间点,设这个时间段的长度为l,假设这时候船的倾斜方向为向右,那么我们一行一行分析,假设当前是第i行,对于第j列的时候,能走的最长路程为dp[i][j][k],假设其最大值是从t位置推过来的,那么,对于第j+1的位置,至少应该是从t位置推过来,这个就是单调性了(其他方向是类似的做法)。还有就是k那一维用滚动数组,否则卡内存。整体时间复杂度为o(n*m*k),看起来还是会超时的样子,不过也只能这样了。

表达能力实在是有限。。如果有什么疑问或者见解可以留言讨论。

#include <iostream>#include<stdio.h>#include<string.h>using namespace std;const int INF = -1111111 ;const int maxn = 222 ;char mp[maxn][maxn] ;int dp[2][maxn][maxn] , g , t ;int n , m , x , y , k ;struct Deque {    int val[maxn] , pos[maxn] ;    int star , tail ;    void init () {        star = 1 , tail = 0 ;    }    void pop () {        if ( star <= tail ) star ++ ;    }    void push ( int id , int v ) {        while ( star <= tail && val[tail] < v ) tail -- ;        val[++tail] = v ;        pos[tail] = id ;    }} q ;void solve ( int l , int c ) {    int i , j ;    if ( c == 1 ) {        for ( i = 1 ; i <= m ; i ++ ) {            q.init () ;            int last = 0 ;            for ( j = n ; j >= 1 ; j -- ) {                if ( mp[j][i] == 'x' ) {                    q.init () ;                    continue ;                }                q.push ( j , dp[g][j][i] + j ) ;                while ( q.pos[q.star] > j + l ) q.star ++ ;                last = q.pos[q.star] ;                dp[t][j][i] = max ( dp[t][j][i] , dp[g][last][i] + last - j ) ;                dp[t][j][i] = max ( dp[t][j][i] , dp[g][j][i] ) ;            }        }    }    else if ( c == 2 ) {        for ( i = 1 ; i <= m ; i ++ ) {            q.init () ;            int last = 0 ;            for ( j = 1 ; j <= n ; j ++ ) {                if ( mp[j][i] == 'x' ) {                    q.init () ;                    continue ;                }                q.push ( j , dp[g][j][i] - j ) ;                while ( q.pos[q.star] < j - l ) q.star ++ ;                last = q.pos[q.star] ;                dp[t][j][i] = max ( dp[t][j][i] , dp[g][last][i] + j - last ) ;                dp[t][j][i] = max ( dp[t][j][i] , dp[g][j][i] ) ;            }        }    }    else if ( c == 3 ) {        for ( i = 1 ; i <= n ; i ++ ) {            q.init () ;            int last = 0 ;            for ( j = m ; j >= 1  ; j -- ) {                if ( mp[i][j] == 'x' ) {                    q.init () ;                    continue ;                }                q.push ( j , dp[g][i][j] + j ) ;                while ( q.pos[q.star] > j + l ) q.star ++ ;                last = q.pos[q.star] ;                dp[t][i][j] = max ( dp[t][i][j] , dp[g][i][last] - j + last ) ;                dp[t][i][j] = max ( dp[t][i][j] , dp[g][i][j] ) ;          //      printf ( "fuck dp[%d][%d] = %d\n" , i , j , dp[t][i][j] ) ;         //       printf ( "dp[%d][%d] = %d\n" , i , last , dp[g][i][last] ) ;            }        }    }    else {        for ( i = 1 ; i <= n ; i ++ ) {            q.init () ;            int last = 0 ;            for ( j = 1 ; j <= m ; j ++ ) {                if ( mp[i][j] == 'x' ) {                    q.init () ;                    continue ;                }                q.push ( j , dp[g][i][j] - j ) ;                while ( q.pos[q.star] < j - l ) q.star ++ ;                last = q.pos[q.star] ;                dp[t][i][j] = max ( dp[t][i][j] , dp[g][i][last] + j -last ) ;                dp[t][i][j] = max ( dp[t][i][j] , dp[g][i][j] ) ;            }        }    }}int main() {    int i , j ;    while ( scanf ( "%d%d%d%d%d" , &n , &m , &x , &y , &k ) != EOF ) {        for ( i = 1 ; i <= n ; i ++ )            scanf ( "%s" , mp[i] + 1 ) ;        g = 0 ;        t = 1 ;        for ( i = 1 ; i <= n ; i ++ )            for ( j = 1 ; j <= m ; j ++ )                dp[g][i][j] = dp[t][i][j] = INF ;        dp[g][x][y] = 0 ;        for ( i = 1 ; i <= k ; i ++ ) {            int a , b , c ;            scanf ( "%d%d%d" , &a , &b , &c ) ;            solve ( b - a + 1 , c ) ;            swap ( g , t ) ;    //        for ( j = 1 ; j <= n ; j ++ )        //        for ( a = 1 ; a <= m ; a ++ )           //         printf ( "dp[%d][%d] = %d\n" , j , a , dp[g][j][a] ) ;        }        int ans = 0 ;        for ( i = 1 ; i <= n ; i ++ )            for ( j = 1 ; j <= m ; j ++ )                ans = max ( ans , dp[g][i][j] ) ;        printf ( "%d\n" , ans ) ;    }    return 0;}


原创粉丝点击