P2254 NOI2005 瑰麗華爾茲

2022-02-27 09:02:29 字數 2280 閱讀 9102

單調佇列優化dp

思路感覺比較簡單,但也許是最近降智嚴重,**實現的時候還自閉了一會/kk

\(n,m\le 200,k\le 200,t\le 40000\)

發現區間個數比較小,可以考慮從 \(k\) 開始入手,也就是挨個考慮每個時間區間的情況來轉移

因為每個區間內傾斜方向相同,也就是這段時間內只能往乙個方向走或不走

那麼,\([s,t]\) 區間,它能朝著對應的傾斜方向走 \(0\sim t-s+1\) 步

所以設 \(f(now,i,j)\) 表示在第 \(now\) 個時間區間結束後,以座標 \((i,j)\) 為終點,最多移動多少個格仔

轉移的式子以向上為例,那麼 \(f(now,i,j)\) 由 \(f(now-1,[i-t+s-1,i],j)\) 轉移來,其它方向當然也都相似

\[f(now,i,j)=\max_^ f(now-1,k,j)+(i-k)

\]後面的 \(i-k\) 就是在本次區間內移動的距離

一開始腦子傻掉居然直接在**裡寫成由 \(f(now,[i-t+s-1],j)\) 轉移到 \(f(now,i,j)\) 。。。。果然還是要把轉移方程在紙上好好寫一遍在開始寫**

然後這樣做複雜度是 \(o(kn^3)\),超時,要用單調佇列優化一下

發現單調佇列裡的數是一直在變化的(上面說的 \(i-k\) 造成的),不方便比較,但是可以比較它們的「相對大小」

什麼意思呢,就是每次往單調佇列裡放入的數是 \(f(now-1,i,j)+wei\),並每次讓 \(wei\) 減一

原因:設 \(f(now-1,i,j)=f(now-1,i+1,j)+x\),如果都要對乙個 \((p,j)\) 來進行轉移,那麼 \(f(now-1,i,j)\) 會比 \(f(now-1,i+1,j)\) 轉移後的結果多 \(x+1\)

當然是因為 \(p-i\) 比 \(p-(i+1)\) 多一

所以前面的乙個數入隊的時候,要比後面的數入隊的時候多加乙個 \(1\)

那麼取佇列中最大值的時候,也不能直接用佇列的值(那只體現了相對的大小),而是用最大值對應的下標(設其為 \(ind\))

則 \(f(now,i,j)=f(now-1,ind,j)+(i-ind)\)

所以複雜度就是 \(o(kn^2)\) 了

**,同一函式複製四遍,不過感覺這樣看起來似乎比通過不同引數呼叫同一函式來實現舒服,也更好寫

#include#include#include#include#include#include#include#define reg register

#define en std::puts("")

#define ll long long

inline int read()

while(c>='0'&&c<='9')

return y?x:-x;

}inline int abs(int x)

int head,tail;

int num[205],ind[205];

inline void push(int x,int index,int len)

int n,m;

int map[205][205];

int f[205][205][205];

char ss[205];

//up,down 都是把 i 放入佇列的 ind

inline void work1(int now,int len)

else

} }}inline void work2(int now,int len)

else

} }}//left,right 都是把 j 放入佇列的 ind

inline void work3(int now,int len)

else

} }}inline void work4(int now,int len)

else

} }}int main()

for(reg int aa=0;aa<=k;aa++)

for(reg int i=0;i<=n;i++)for(reg int j=0;j<=m;j++) f[aa][i][j]=-1e9;

f[0][sx][sy]=0;

for(reg int i=1;i<=k;i++)

int ans=0;

for(reg int i=1;i<=n;i++)for(reg int j=1;j<=m;j++) ans=std::max(ans,f[k][i][j]);

std::printf("%d",ans);

return 0;

}

P2254 NOI2005 瑰麗華爾茲

單調佇列優化線性dp 單調佇列中只需儲存下標 只能優化最內層迴圈 dp c 1 x y dp c 1 x que tl dis x,y,x,que tl 時才將隊尾元素出隊 而不僅僅是dp c 1 x y dp c 1 x que tl 即 用隊中所存下標對應狀態對當前狀態的貢獻為依據選擇是否留在隊...

luoguP2254 NOI2005 瑰麗華爾茲

題目比較好,人比較菜。include define maxn 205 using namespace std int n,m,x,y,k,f maxn maxn maxn l,r,d,dx 7 dy 7 l,r,q maxn ans 0 char tu maxn maxn int main mems...

Luogu 2254 NOI2005 瑰麗華爾茲

簡單dp,設 f 表示第i個時間段,鋼琴處在 j,k 位置移動距離的最大值,那麼有轉移 f max f f max f 其中 j dx len leq a leq j 1 k dy len leq b leq k 1 len ed st 1 其實就是乙個滑動視窗,考慮到轉移順序,就是寫四遍單調佇列 ...