[我csdn的部落格]
(我洛谷的部落格
說明啊,它可以用單調佇列
易推出
dp[x][y][t] = max(dp[x`][y`][t - 1] + 1,dp[x][y][t]);
然後看一下資料範圍???
n,m≤200,k≤200,t≤40000
o(n^3)
顯然,tle
然後老師講了優化方案
t可以換成k
因為任一區間時間內,都只向乙個方向走
。。。然後就可以得到轉移方程
dp[x][y][k] = max(dp[x][y][k],dp[x1][ y1][k-1] + abs(x - x1) + abs(y - y2));`
x1 y2 表示在x,y的前提下,dp[x1][y1][k - 1] + abs(x - x1) + abs(y - y2))的值最大(在範圍內)
'o(n^3)'
等等,時間複雜度貌似沒減
就是我們的單調佇列神奇登場的時候了
優化最內層迴圈
滾動優化
dp[x][y][k] 空間複雜度不小
可以發現
dp[x][y][k] 只跟上一次(dp[x][y][k - 1])有關且滿足x,y是單調遞增或遞減的
滾動優化一下
函式優化4個方向
相信沒有人會實誠de用4個if一一處理
所以我們用乙個函式
傳進去的 必須要有 限制·對應的哪種方向(用陣列存一下向迷宮中的四個方向)·當前起點
單調佇列
單調佇列中的元素不僅要看它自身的值,還要看。val + 它到當前點的距離(在移動範圍內)
哪如何實現了
它到當前點的距離可以
abs(x - q[index].x) + abs(y - q[index].y)
放入佇列時我是這樣搞的
while(tail >= head&&dp[x][y] > q[tail].val + m(tail))
tail--;
但我們如何保證迴圈結束後取出來的就是最大值?(m()巨集定義,詳見code)
每個元素都是這樣放進去的
那麼假設佇列q=(都是val值)
在列舉點時,每次距離都要加一
1 + 1 = 2
2 + 1 = 3
3 + 1 = 4
q =
順序沒有發生改變
注意由於滾動優化後了,處理乙個點時只能先放入單調佇列
再取出當前最大值
還有x
,是不能走的,遇到就重新清一下佇列(把head = 1,tail = 0)
#include #include #define m(index) abs(x - q[index].x) + abs(y - q[index].y)
using namespace std;
const int maxn = 202;
bool map[maxn][maxn];
int n,m,dp[maxn][maxn],ans;
int dir[4][2] = ,,,};
class t
;templateinline tt max(tt a,tt b)
templateinline tt abs(tt a)
inline void dp(int x,int y,int con,int s)
}int main()
}memset(dp,-0x7f7f7f,sizeof(dp));
dp[x][y] = 0;
for(i = 1;i <= k;i++)
printf("%d",ans);
return 0;
}
DP 單調佇列 瑰麗華爾茲
題意 給定乙個n行m列的矩陣,矩陣的某些方格上有障礙物。乙個人從給定起點開始滑行,每次滑行都有乙個滑行方向,你可以在0 ci之中選擇這次滑行長度。滑行過程中不能碰到障礙物。求最長的滑行距離。n,m,滑行次數k 200。ci之和 40000。思路 參考這篇文章 然而不會實現 膜hzwer的 inclu...
BZOJ1499 瑰麗華爾茲(單調佇列)
pro 給出乙個n m的地圖,剛開始人在 x,y 每次給出一段區間 l,r,t 表示在時間 l,r 內,可以使人向4個方向 t 移動一格,或者不動。求最大可以移動多少格。sol 考慮每一列 上下移 或者一行 左右移 的情況。以右移為例,我們可以很快列出dp方程 f x y i max f x y i...
NOI 2005 瑰麗華爾茲 DP 單調佇列
time limit 3 sec memory limit 64 mb submit 490 solved 250 submit status discuss 你跳過華爾茲嗎?當 響起,當你隨著旋律滑動舞步,是不是有一種漫步仙境的愜意?眾所周知,跳華爾茲時,最重要的是有好的 但是很少有幾個人知道,世...