Snakes【区间DP】Rating

题目描述:

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≤106) 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.

Example
input
6 2
7 9 8 2 3 2
output
3
Note
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.

思路:

首先看题目是要用到DP思想。第一个循环算出输入序列的前缀和。之后初始化dp数组为无穷。第二个循环算出如果在没有更改的机会的条件下,每个位置之前所浪费的空间的最大值。第三个循环的第二层要从(i+1)开始,因为起始的大小是不用改的,所以比如有一次机会时要至少有2个数才能有改的机会,这也是为什么第三层循环每次左游标(m)运动到 i 就要结束。状态转移方程的大概操作是右游标(j)不断向右移动扩大总范围,每次循环相当于从右往左,把总范围分成(i+1)个子区间,每个子区间通过左游标一个一个向左移动算出最优解,最后子区间相加得出(j)位置的最优解。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef unsigned long long ll;
const int mod=1e6+7;
 
int main()
{
    int N,K;
    cin>>N>>K;
    int a[410],pre[410];
    int dp[410][410];
    for(int i=1; i<=N; i++)
    {
        cin>>a[i];
        pre[i]=pre[i-1]+a[i];
    }
    memset(dp,mod,sizeof(dp));
    int key=a[1];
    for(int i=1; i<=N; i++)
    {
        key=max(a[i],key);
        dp[i][0]=(key*i)-(pre[i]-pre[0]);
    }
    for(int i=1; i<=K; i++)
    {
        for(int j=i+1; j<=N; j++)
        {
            key=a[j];
            for(int m=j-1; m>=i; m--)
            {
                key=max(a[m+1],key);
                dp[j][i]=min(dp[j][i],dp[m][i-1]+key*(j-m)-(pre[j]-pre[m]));
            }
        }
    }
    cout<<dp[N][K]<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值