JZOJ-senior-1773. 【NOIP動態規劃專題】猴子
阿新 • • 發佈:2018-11-08
Time Limits: 1000 ms Memory Limits: 65536 KB
Description
一個猴子找到了很多香蕉樹,這些香蕉樹都種在同一直線上,而猴子則在這排香蕉樹的第一棵樹上。這個猴子當然想吃盡量多的香蕉,但它又不想在地上走,而只想從一棵樹跳到另一棵樹上。同時猴子的體力也有限,它不能一次跳得太遠或跳的次數太多。每當他跳到一棵樹上,它就會把那棵樹上的香蕉都吃了。那麼它最多能吃多少個香蕉呢?
Input
輸入第一行為三個整數,分別是香蕉樹的棵數N,猴子每次跳躍的最大距離D,最多跳躍次數M。 下面N行每行包含兩個整數,ai,bi,分別表示每棵香蕉樹上的香蕉數,以及這棵樹到猴子所在樹的距離。輸入保證這些樹按照從近到遠排列,並且沒有兩棵樹在同一位置。b0總是為0。
Output
輸出只有一行,包含一個整數,為猴子最多能吃到的香蕉數。
Sample Input
5 5 2 6 0 8 3 4 5 6 7 9 10
Sample Output
20
Data Constraint
ai<=10000,D<=10000 100%的資料有M<N<=2000,bi<=10000
Solution
- 顯然DP,設 表示跳了 次,到達第 棵樹上的能吃到的最多的香蕉數
- 那麼 )(b[j]-b[k]<=D)
- 乍一看, ,於是考慮優化DP
- 容易發現,對於跳同樣步數的決策
- 要是決策 不僅能吃到更多的香蕉,而且能到達更遠的位置,那麼決策 就沒有了意義
- 於是我們用單調佇列優化即可
Code
#include<algorithm>
#include<cstdio>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int N=2010;
int n,m,k,ans;
int a[N],d[N],q[N],f[N][N];
int main()
{
freopen("monkey.in","r",stdin);
freopen("monkey.out","w",stdout);
scanf("%d%d%d",&n,&k,&m);
fo(i,1,n) scanf("%d%d",&a[i],&d[i]);
f[0][1]=a[1];
fo(i,1,m)
{
int l=1,r=0;
fo(j,i+1,n)
{
while(r>=l&&f[i-1][j-1]>=f[i-1][q[r]]) --r;
q[++r]=j-1;
while(d[j]-d[q[l]]>k) ++l;
f[i][j]=f[i-1][q[l]]+a[j];
ans=max(ans,f[i][j]);
}
}
printf("%d",ans);
}