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 }