單調佇列優化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 其實就是乙個滑動視窗,考慮到轉移順序,就是寫四遍單調佇列 ...