1. 程式人生 > 實用技巧 >【題解】menit的運動計劃

【題解】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]\)

來說,自己可以等於 \(k\) 分鐘前,疲勞度剛好為 \(k\) 的值或上一分鐘休息,這一分鐘繼續休息的值。

對於 \(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.