【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; }