這是一道思路比較簡單但是除錯極其毒瘤的一道題目!
乙個猴子找到了很多香蕉樹,這些香蕉樹都種在同一直線上,而猴子則在這排香蕉樹的第一棵樹上。這個猴子當然想吃盡量多的香蕉,但它又不想在地上走,而只想從一棵樹跳到另一棵樹上。同時猴子的體力也有限,它不能一次跳得太遠或跳的次數太多。每當他跳到一棵樹上,它就會把那棵樹上的香蕉都吃了。那麼它最多能吃多少個香蕉呢?
輸入第一行為三個整數,分別是香蕉樹的棵數n
'>n
n,猴子每次跳躍的最大距離d
'>d
d,最多跳躍次數m
'>m
m。 下面n
'>n
n行每行包含兩個整數ai,
bi'>ai,bi
ai,bi,分別表示每棵香蕉樹上的香蕉數,以及這棵樹到猴子所在樹的距離。輸入保證這些樹按照從近到遠排列,並且沒有兩棵樹在同一位置。b
0'>b0
b0總是為0。
輸出只有一行,包含乙個整數,為猴子最多能吃到的香蕉數。
input
5 5 2output6 08 3
4 56 7
9 10
20對於30%的資料,1≤m
100'>1≤m
1≤m對於50%的資料,1≤m
2000
'>1≤m
1≤m對於100%的資料,1≤m
5000,a
i≤10000,b
i≤10000,d
≤10000
'>1≤m
1≤m時間限制:1
s'>1s
1s空間限制:256
mb'>256mb
256mb
'>首先是狀態轉移方程dp[k][i]表示到第i棵數已經跳了k步的最多香蕉數
256mb
'>那麼轉移就是dp[k][i]=max(dp[k-1][q[head]]+val[i],dp[k][i]);
256mb
'>然後呢就是毒瘤的單調佇列時間
就是這種資料結構,把它弄成單調的,head彈出,tail插入;
在陣列裡是把整個佇列倒過來放進去的
因為是單調佇列
所以插入時候tail--找到要插的位置,然後再++tail位置插進去
彈出時候head++,就彈出了
也就是說在陣列裡head在左,tail在右,可以腦補這個佇列就躺在陣列裡
一定要注意head要<=tail,要不可能會死迴圈(網上有個**就被我hack了)
這道題有一些注意的地方;
有幾組資料比較毒瘤,有可能有兩個樹之間距離很大,導致後面的樹全都去不了(見16行特判,被卡掉了30分),這時候需要特殊處理(我直接輸出,會跑的很快2333)
上**!
1 #include2 #include3 #include4 #include5using
namespace
std;
6int n,d,m,head=1,tail=1,ans=-1;7
int val[5111],s[5111],dp[5111][5111],q[5111];8
intmain()
923 q[tail]=k;
24for(int i=k+1;i<=n;i++)
2533}34
for(int i=1;i<=n;i++)ans=max(ans,dp[m][i]);
35 printf("
%d\n
",ans);
36return0;
37 }
單調佇列優化
單調佇列是一種嚴格單調的佇列,可以單調遞增,也可以單調遞減。隊首位置儲存的是最優解,第二個位置儲存的是次優解。單調佇列可以有兩個操作 1 插入乙個新的元素,該元素從隊尾開始向隊首進行搜尋,找到合適的位置插入之,如果該位置原本有元素,則替換它。2 在過程中從隊首刪除不符合當前要求的元素。單調佇列實現起...
單調佇列 優化DP
佇列元素保持單調遞增 減 而保持的方式就是通過插隊,把隊尾破壞了單調性的數全部擠掉,從而使佇列元素保持單調。單調佇列的作用 優化dp。許多單調佇列優化的dp可以使複雜度直接降維,下面就以最簡單的一道題為例 在某兩座城市之間有 n 個烽火台,每個烽火台發出訊號都有一定代價。為了使情報準確地傳遞,在連續...
單調佇列優化dp
形如f i max wi的問題都可以用單調佇列優化。例題 板題 注意乙個地方 求完所有的f後 ans不是f n 而是後面的一段字尾的f 注意字尾的左端點。很顯然是rmq問題 計算字首和sum i 對於固定的右端點 i,我們想讓答案最大等價於max,可以用個單調佇列維護。但是隨便乙個資料結構直接on ...