USACO3.4.4--Raucous Rockers

Raucous Rockers

You just inherited the rights to N (1 <= N <= 20) previously unreleased songs recorded by the popular group Raucous Rockers. You plan to release a set of M (1 <= M <= 20) compact disks with a selection of these songs. Each disk can hold a maximum of T (1 <= T <= 20) minutes of music, and a song can not overlap from one disk to another.

Since you are a classical music fan and have no way to judge the artistic merits of these songs, you decide on the following criteria for making the selection:

  • The songs on the set of disks must appear in the order of the dates that they were written.
  • The total number of songs included will be maximized.

PROGRAM NAME: rockers

INPUT FORMAT

Line 1: Three integers: N, T, and M.
Line 2: N integers that are the lengths of the songs ordered by the date they were written.

SAMPLE INPUT (file rockers.in)

4 5 2

4 3 4 2

OUTPUT FORMAT

A single line with an integer that is the number of songs that will fit on M disks.

SAMPLE OUTPUT (file rockers.out)

3
题解:这题可以用动态规划来做也可以用枚举来做。
第一种方法:枚举(可以参考byvoid大牛的解析)。枚举量为2^20=1048576(时间上还是允许的),即在N首歌的所有非空子集,然后算出每种情况所有光盘上能够刻录的歌曲总数目,记录最大值即可。可以用位运算来做,非常的简单和直白。
第二种方法:动态规划。定义一个三维数组f.
状态转移方程为:f[i][j][k]=max(f[i-1][j][k],f[i][j-1][k])(time[i]>k)
Or max(f[i-1][j][k-time[i]]+1,f[i-1][j-1][T]+1)(time[i]<=k)
f[i][j][k]表示前i首歌曲,刻录在j个光盘中,第j张光盘用了k分钟可以刻录最多的歌曲数量。
f[i-1][j][k]表示不选择第i首歌曲,f[i][j-1][k]表示第i首歌曲刻录在第j-1个光盘中。
f[i-1][j][k-time[i]]表示第i首歌刻录在第j张光盘中,f[i-1][j-1][T]表示第i首歌单独刻录在第j张光盘上,并取前i-1首歌刻录在前j-1张光盘的最优值。
View Code
 1 /*

 2 ID:spcjv51

 3 PROG:rockers

 4 LANG:C

 5 */

 6 #include<stdio.h>

 7 #include<string.h>

 8 #define MAXN 25

 9 int max(int a,int b)

10 {

11     return a>b?a:b;

12 }

13 int main(void)

14 {

15     freopen("rockers.in","r",stdin);

16     freopen("rockers.out","w",stdout);

17     int f[MAXN][MAXN][MAXN],time[MAXN];

18     int i,j,k,t,n,m;

19     scanf("%d%d%d",&n,&t,&m);

20     for(i=1;i<=n;i++)

21     scanf("%d",&time[i]);

22     memset(f,0,sizeof(f));

23     for(i=1;i<=n;i++)

24     for(j=1;j<=m;j++)

25     for(k=0;k<=t;k++)

26     if(k<time[i])

27     f[i][j][k]=max(f[i-1][j][k],f[i][j-1][k]);

28     else

29     f[i][j][k]=max(f[i-1][j][k-time[i]]+1,f[i-1][j-1][t]+1);

30     printf("%d\n",f[n][m][t]);

31     return 0;

32 }

 






你可能感兴趣的:(USACO)