瑰麗華爾茲 單調佇列

2022-05-07 22:00:08 字數 1983 閱讀 6441

[我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 你跳過華爾茲嗎?當 響起,當你隨著旋律滑動舞步,是不是有一種漫步仙境的愜意?眾所周知,跳華爾茲時,最重要的是有好的 但是很少有幾個人知道,世...