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和K,
第二行包含N个整数,a1,…,aN,其中ai(0≤ai≤106)是第i组的蛇的数量。
输出
输出一个整数,给出贝西捕获所有蛇后的最小浪费空间量。
2020.2.22GDUT寒假训练排位赛2-B_第1张图片

题目分析:

每次使用变形,都可以抓捕连续的几组蛇,假如使用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

代码实现:

#include 
#include 
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;
}

你可能感兴趣的:(2020.2.22GDUT寒假训练排位赛2-B)