【USACO1996】录制唱片

题目描述

贝西想从奶牛摇滚乐队的 N 首歌里挑出一些录制一套专辑。专辑分 K 张唱片,每张唱片可容纳 总长为 C 分钟的歌曲。第 i 首歌的长度为 Ti 分钟,录制唱片时,唱片之间的歌曲需要保持原本的顺 序。第一张唱片里的歌必须排在第二张唱片前面,之后的每张唱片里也是如此。同时,每首歌曲必须 完整地放在一张唱片里,不然,就只能舍去不录了。请问贝西应该选哪些歌曲,才能让专辑里装下的 歌曲尽量多?

输入格式

 第一行:三个整数 N, K 和 C, 1 ≤ N ≤ 1000 , 1 ≤ K ≤ 1000 , 1 ≤ C ≤ 1000 • 第二行到第 N + 1 行:第 i + 1 行有一个整数 Ti, 1 ≤ Ti ≤ 1000

输出格式

单个整数:表示可以装进专辑的歌曲数目

样例输入

 

4 2

5

4

3

4

2

样例输出

3

题解

 

设f[i,j]表示前i首歌录了j首所需的最少唱片数,g[i,j]表示前i首歌录了j首当前唱片使用了多少容量。

 

f[i,j]=min(f[i-1,j-1](+1),f[i-1,j])

 

如果第i首歌要录并且能录进当前唱片里,f[i,j]= f[i-1,j-1],

如果录不进,另开一张唱片,f[i,j],=f[i-1,j-1]+1;

如果第i首歌不录,并且使用的唱片数小于第i首歌录进去的唱片数,自然不录,如果相等,选择当前唱片使用容量最少的方案,这样以后才能录更多。这里记得要保证i!=j(否则就变成前i-1首歌录了i首)。

 

 

#include <cstdio>
int n,m,c,a[1005],f[1005][1005],g[1005][1005];
const int inf=2147483647/4;
int main()
{
    int i,j;
    scanf("%d%d%d",&n,&m,&c);
    for (i=1;i<=n;i++)
      scanf("%d",&a[i]);
    for (i=1;i<=n;i++)
      for (j=1;j<=n;j++)
        f[i][j]=inf; 
    for (i=1;i<=n;i++)
      for (j=1;j<=i;j++)
      {
            if (g[i-1][j-1]+a[i]<=c)
              f[i][j]=f[i-1][j-1],
              g[i][j]=g[i-1][j-1]+a[i];
            else if (a[i]<=c)
              f[i][j]=f[i-1][j-1]+1,
              g[i][j]=a[i];
            if (i!=j && ((f[i-1][j]<f[i][j]) || (f[i-1][j]==f[i][j] && g[i-1][j]<g[i][j])))
              f[i][j]=f[i-1][j],
              g[i][j]=g[i-1][j];  
      }
    for (i=n;i>=1;i--)
      if (f[n][i]<m)
        break;
    printf("%d",i);      
    return 0;
}

 

posted @ 2017-11-08 08:07  SAKURA12  阅读(249)  评论(0编辑  收藏  举报