排位賽Ⅱ B

B. Snakes

題目
題目鏈接
題目大意:
農夫抓蛇,有N組蛇,每組蛇有一定的數目,農夫需用籃子來抓蛇,一開始農夫可用任意容量(size)來抓蛇,每抓完一組就記錄剩餘容量(爲浪費的空間),然後籃子清空繼續抓捕下一組蛇時,並且農夫有K次機會改變籃子的容量,問農夫抓完所有蛇後,浪費的空間的最小值是多少。
思路:
農夫每次抓捕區間組數爲l-r的蛇時,籃子容量需要等價於數目最大那組,這個我們可以通過枚舉來得到區間最大的一組蛇的數目。接下來就是dp了,我們可以設置dp[i][k],i爲目前抓捕到第i組蛇,k爲農夫當前改變籃子容量的次數。一個區間l-r中浪費的空間大小是maxn*(r-l+1)(maxn爲該區間中數量最大的一組蛇的數目),由此我們可以得到一個狀態方程,dp[i][j]=min(dp[i][j],dp[m][j-1]+maxn(r-l+1))(m爲第j-1次修改的籃子所抓取的最後一組蛇的下標)。我們可以很容易的知道j<i的,因爲分成j組的話最少需要j+1個元素纔行。所以枚舉m時只需枚舉j到i-1。
代碼:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int a[450],dp[450][450],s[450];
const int inf=999999999;
int main(){
	fill(dp[0],dp[0]+450*450,inf);
	memset(s,0,sizeof(s));
	int n,k,maxn=-1;
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		s[i]=s[i-1]+a[i];//前綴和。
		maxn=max(a[i],maxn);
		dp[i][0]=maxn*i-s[i];//先處理0次修改的狀態。
	}
	for(int j=1;j<=k;j++){
		for(int i=j+1;i<=n;i++){
			maxn=-1;//初始化。
			for(int m=i-1;m>=j;m--){
				maxn=max(a[m+1],maxn);//選出最大的。
				dp[i][j]=min(dp[i][j],dp[m][j-1]+maxn*(i-m)-(s[i]-s[m]));
			}
		}
	}
	cout<<dp[n][k]<<endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章