【題解】menit的運動計劃
題目描述
monkeys打算通過跑步來培養自己的運動細胞,作為其中的一員,menit選擇的運動方式是每天進行 \(N(1\le N\le10000)\) 分鐘的跑步訓練。在每分鐘的開始,menit會選擇下一分鐘是用來跑步還是停下休息。
menit的體力限制了她跑步的距離。更具體地,如果menit選擇在第 \(i\) 分鐘內跑步,她可以在這一分鐘內跑 \(D_i(1\le D_i\le1000)\) 米,並且她的疲勞度會增加 \(1\) 。不過,無論何時menit的疲勞度都不能超過 \(M(1\le M\le500)\)。如果menit選擇停下休息,那麼她的疲勞度就會每分鐘減少 \(1\) ,但她必須休息到疲勞度恢復到 \(0\)為止。在疲勞度為0時休息的話,疲勞度不會再變動。跑步開始時,menit的疲勞度為 \(0\) 。 還有,在 \(N\) 分鐘的跑步訓練結束時,menit的疲勞度也必須恢復到 \(0\),否則她將沒有足夠的精力來對付這一整天中剩下的事情。 請你計算一下,menit最多能跑多少米。
輸入格式
第 \(1\) 行: \(2\) 個用空格隔開的整數:\(N\) 和 \(M\) 第 \(2..N+1\) 行: 第 \(i+1\) 為 \(1\) 個整數:\(D_i\)
輸出格式
輸出 \(1\) 個整數,表示在滿足所有限制條件的情況下,menit能跑的最大距離
樣例
樣例輸入
5 2 5 3 4 2 10
樣例輸出
9
樣例說明
menit在第 \(1\) 分鐘內選擇跑步(跑了 \(5\) 米),在第 \(2\) 分鐘內停下來休息,在第 \(3\) 分鐘內跑步(跑了 \(4\) 米),剩餘的時間都用來休息。因為在跑步結束時menit的疲勞度必須為 \(0\) ,所以她不能在第 \(5\) 分鐘內選擇跑步。
資料範圍與提示
\(10\%\)資料 \(n\le5\)
\(40\%\)資料 \(n\le100\)
\(100\%\)資料 \(n\le10000,m\le500\)
Solution
簡單DP。
設計狀態:
f[i][j] 表示第 i 分鐘,疲勞值為 j 的最大方案
狀態轉移方程:
對於 \(f[i][0]\)
對於 \(f[i][j](j>0)\) 來說,自己只能等於上一分鐘,疲勞值減一加上這一分鐘可以跑的距離。
由此推出狀態轉移方程:
\[f[i][j]=\begin{cases}\max(\max(f[i-k][k]),f[i-1][0])&j=0\\f[i-1][j-1]+d[i]&j>0\end{cases} \]Code
#include<cstdio>
int n,m;
int d[10005];
int f[10005][505];
int max(int x,int y){
return x>y?x:y;
}
int main(){
freopen("cowrun.in","r",stdin);
freopen("cowrun.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&d[i]);
for(int i=1;i<=n;++i){
f[i][0]=f[i-1][0];
for(int j=1;j<=i;++j)
f[i][0]=max(f[i][0],f[i-j][j]);
for(int j=1;j<=m;++j)
f[i][j]=max(f[i][j],f[i-1][j-1]+d[i]);
}
printf("%d",f[n][0]);
return 0;
}
end.