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;}
- zstu3924 [NOI2005]瑰丽华尔兹 (单调队列dp)
- [NOI2005]瑰丽华尔兹 && dp单调队列
- 【DP】【单调队列】【NOI2005】瑰丽华尔兹
- bzoj1499 [NOI2005]瑰丽华尔兹(dp+单调队列)
- NOI2005瑰丽华尔兹-单调队列
- 【noi2005试题】瑰丽华尔兹 单调队列优化DP
- 【bzoj1499】[NOI2005]瑰丽华尔兹(dp+单调队列优化)
- bzoj1499 [NOI2005]瑰丽华尔兹 (单调队列优化DP)
- bzoj1499 [NOI2005]瑰丽华尔兹(luoguP2254)(dp+单调队列)
- BZOJ 1499 NOI2005 瑰丽华尔兹 单调队列
- [DP 暴力 || ST表 || 单调队列] BZOJ 1499 [NOI2005]瑰丽华尔兹
- NOI 2005 瑰丽华尔兹(DP+单调队列)
- [NOI 2005] 瑰丽华尔兹:dp+单调队列
- 【NOI2005T1】瑰丽华尔兹-DP单调队列优化
- BZOJ 1499 [NOI2005]瑰丽华尔兹 动态规划(+单调队列)
- wikioi-1748 瑰丽华尔兹 -单调队列优化DP
- [BZOJ 1499][NOI 2005]瑰丽华尔兹(DP+单调队列优化)
- [BZOJ1499][NOI2005][DP+优化]瑰丽华尔兹
- 小感
- NYOJ 73 比大小
- Xcode常见的程序崩溃及其调试
- tampermonkey应用二--Bit币提醒(第三版)
- JDBC连接池基础
- zstu3924 [NOI2005]瑰丽华尔兹 (单调队列dp)
- linux字符集编码转换与iconv使用简单示例
- escape
- Android——UI——选项卡(Tab)
- java连接常见数据库的连接字符串
- 斗地主原型:equals要重写.同时也要重写出:hashCode
- LeetCode 之 Remove Element
- C++获得所有网卡信息
- zju——涨价了