usaco Snakes (dp)

题面:

According to legend, St. Patrick banished all of the snakes in Mooland over a thousand years ago. However, snakes have since made their way back to Mooland! St. Patrick’s day was on March 17, so Bessie is going to commemorate St. Patrick by banishing all of the snakes from Mooland once and for all.

Bessie is equipped with a net to capture snakes distributed in N groups on a line (1≤N≤400) . Bessie must capture every snake in every group in the order that the groups appear on the line. Each time Bessie captures a group, she can put the snakes in a cage and start with an empty net for the next group.

A net with size s means that Bessie can capture any group that contains g snakes, where g≤s . However, every time Bessie captures a group of snakes of size g with a net of size s, she wastes s-g space. Bessie’s net can start at any size and she can change the size of her net K times (1≤K<N)

Please tell Bessie the minimum amount of total wasted space she can accumulate after capturing all the groups.

INPUT
The first line contains N and K. The second line contains N integers, a1,…,aN , where ai (0≤ai≤1e6) is the number of snakes in the ith group.

OUTPUT
Output one integer giving the minimum amount of wasted space after Bessie captures all the snakes.

SAMPLE INPUT:
6 2
7 9 8 2 3 2

SAMPLE OUTPUT:
3
Bessie’s net starts at a size of 7. After she captures the first group of snakes, she changes her net to a size of 9 and keeps that size until the 4th group of snakes, when she changes her net to size 3. The total wasted space is (7-7)+(9-9)+(9-8)+(3-2)+(3-3)+(3-2)=3.


题意:

Bessie装备了一个捕网,用来捕捉N组排成一行的蛇(1≤N≤400)。Bessie必须按照这些组在这一行中出现的顺序捕捉每一组的所有蛇。每当Bessie抓完一组蛇之后,她就会将蛇放在笼子里,然后带着空的捕网开始捕捉下一组。

一个大小为s的捕网意味着Bessie可以抓住任意包含g条的一组蛇,其中g≤s。然而,每当Bessie用大小为s的捕网抓住了一组g条蛇,就意味着浪费了s-g的空间。Bessie可以任意设定捕网的初始大小,并且她可以改变K次捕网大小(1≤K<N)。

请告诉Bessie她捕捉完所有组的蛇之后可以达到的总浪费空间的最小值。


思路:

观察浪费空间,发现对于一段区间[l,r]来说,网的大小肯定要等于该区间内最大的那组蛇的数量记为maxn,那么对于这段区间花费的总空间就是maxn*(r-l+1),而实际用的空间则是这段区间内蛇的数量之和,用前缀和sum[r]-sum[l-1]表示。这样就可以表示出浪费的空间:maxn*(r-l+1)-(sum[r]-sum[l-1])。

定义dp[i][j]表示到第i个位置,变化了j次容量,的最小的浪费空间。
转移方程:dp[i][j]=min(dp[i][j],dp[s][j-1]+maxn*(r-l+1)-(sum[r]-sum[l-1])),其中r=i,l=s+1,代换后:dp[i][j]=min(dp[i][j],dp[s][j-1]+maxn*(i-s)-(sum[i]-sum[s]))

maxn通过s从后往前(i-1到j)枚举可以直接得到,不需要额外处理。

需要注意,第一个是不要变容量的所以dp[i][j]其中i<=j的状态都是无效的,这也是为什么s只枚举到j的原因。

参考代码:
#include<bits/stdc++.h>
using namespace std;
const int N=405;
int a[N],sum[N];
int dp[405][405];

int main(){
    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];
    }
    for(int i=0;i<=401;i++){
        for(int j=0;j<=401;j++){
            dp[i][j]=1000000000;
        }
    }
    int maxn=a[1];
    for(int i=1;i<=n;i++){
        maxn=max(maxn,a[i]);
        dp[i][0]=i*maxn-(sum[i]-sum[0]);
    }

    for(int j=1;j<=k;j++){//枚举变化几次
        for(int i=j+1;i<=n;i++){//枚举位置
            maxn=a[i];
            for(int s=i-1;s>=j;s--){//枚举之前的状态
                maxn=max(maxn,a[s+1]);
                dp[i][j]=min(dp[i][j],dp[s][j-1]+maxn*(i-s)-(sum[i]-sum[s]));
            }
        }
    }

    printf("%d\n",dp[n][k]);
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值