题目
Bessie装备了一个捕网,用来捕捉N组排成一行的蛇(1≤N≤400)。Bessie必须按照这些组在这一行中出现的顺序捕捉每一组的所有蛇。每当Bessie抓完一组蛇之后,她就会将蛇放在笼子里,然后带着空的捕网开始捕捉下一组。
一个大小为s的捕网意味着Bessie可以抓住任意包含g条的一组蛇,其中g≤s。然而,每当Bessie用大小为s的捕网抓住了一组g条蛇,就意味着浪费了s-g的空间。Bessie可以任意设定捕网的初始大小,并且她可以改变K次捕网大小(1≤K<N)。
请告诉Bessie她捕捉完所有组的蛇之后可以达到的总浪费空间的最小值。
解法
dp题,对于第i次捕蛇, 他若选择变化大小,则浪费的空间不会增加,否则,上次变化大小的时候网的大小也应该大于第i组蛇,浪费的空间就是maxn(蛇)* (到上一次变化大小的蛇的组数) - 捕蛇用掉的空间,怎么说呢,讲的也不太明白,本来dp就菜。。看代码吧,代码也写了点注释
代码
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 400 + 100;
int a[maxn], sum[maxn], dp[maxn][maxn]; //蛇的数量、 前缀和、 dp[第i组蛇][变化了j次]
int main(){
memset(dp, 0x3f, sizeof(dp));
int n, k;
scanf("%d%d", &n, &k);
for(int i=1; i<=n; ++i) {
scanf("%d", &a[i]);
sum[i] = sum[i-1] + a[i];
}
int t = a[1];
for(int i=1;i<=n;i++){
t = max(t, a[i]);
dp[i][0] = i*t - sum[i];
}
for(int j=1; j<=k; ++j) { //枚举变化次数
for(int i=j+1; i<=n; ++i) { //变化j次,说明前面至少已经捕捉了j组蛇了
t = a[i]; //当前要捕捉的蛇的数量
for(int m=i-1; m>=j; --m) { //和前面的蛇比较
t = max(a[m+1], t); //如果不变,网的大小只能是距离上次变化前蛇数量的最大值,这样才能捕捉所有蛇
dp[i][j] = min(dp[i][j], dp[m][j-1] + t * (i-m) - (sum[i] - sum[m]));
}
}
}
printf("%d\n",dp[n][k]);
return 0;
}