2020.2.22GDUT寒假训练排位赛2-B

B — Snakes

题目大意:

根据传说,一千多年前,圣帕特里克驱逐了穆尔兰的所有蛇。然而,从那以后,蛇又回到了穆尔兰!圣帕特里克节是在3月17日,所以贝西要永远地从穆尔兰赶走所有的蛇来纪念圣帕特里克。贝西配备有网,可以捕捉N组分布在一条线上的蛇(1≤N≤400)。贝西必须按照每组蛇出现在这条线上的顺序,把每条蛇都抓起来。每次贝西抓住一群蛇,她可以把蛇放在笼子里,然后用空网开始下一群。大小为s的网意味着贝西可以捕获任何含有g条蛇的组,其中g≤s。然而,每当贝西用一张s码的网捕获一群g码的蛇时,她就浪费了s - g码的空间。贝西的网兜可以从任何大小开始,她可以改变网兜的大小K次(1≤K<N)。请告诉贝西,在捕获所有组后,她可以积累的总浪费空间的最小数量。
输入
第一行包含N和K,
第二行包含N个整数,a1,…,aN,其中ai(0≤ai≤106)是第i组的蛇的数量。
输出
输出一个整数,给出贝西捕获所有蛇后的最小浪费空间量。
在这里插入图片描述

题目分析:

每次使用变形,都可以抓捕连续的几组蛇,假如使用1次变形抓捕区间[l,r]组的蛇,那么这个区间最小浪费为maxa*(r-l)-(sum[r]-sum[l]),其中maxa为[l,r]组最多的数目,sum[r]为前r组蛇的总数。
假设现在考虑抓捕第i组,使用m次变形,记为dp[i][m],运用动态规划思想,那么dp[i][m]=min(dp[j][m-1]+maxa*(i-j)-(sum[i]-sum[j])) (1<=j<i,maxa为[j+1,i]最大值)。

代码实现:

#include <iostream>
#include <cstdio>
using namespace std;

const int INF = 999999999;
int n,k;
int a[457];
int sum[457] = {0};
int ans[457][457];

void init()
{
    for(int i=0; i<457; i++)
    {
        for(int j=0; j<457; j++)
        {
            ans[i][j] = INF;
        }
    }
}

int dp()
{
    for(int m=1; m<=k; m++)
    {
        for(int i=m+1; i<=n; i++)   //m次变形最少也要m组蛇,所有m+1开始
        {
            int maxa = 0;
            for(int j=i-1; j>=m; j--)
            {
                maxa = max(maxa,a[j+1]);
                ans[i][m] = min(ans[i][m],ans[j][m-1]+maxa*(i-j)-(sum[i]-sum[j]));
            }
        }
    }
    return ans[n][k];
}

int main()
{
    init(); //初始化
    cin >> n >> k;
    int maxa = 0;
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        sum[i] = sum[i-1]+a[i]; //前i堆蛇总数,即前缀和
        maxa = max(maxa,a[i]);  //前i最大数
        ans[i][0] = maxa*i-sum[i];  //第0次变形时,前i次抓捕的最小浪费
    }
    printf("%d\n",dp());

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值