Raucous Rockers---二维背包

Raucous Rockers

Description

  你刚刚继承了流行的“破锣摇滚”乐队录制的尚未发表的 N( 1 <= N <= 20 ) 首歌的版权。你打算从中精选一些歌曲,发行 M ( 1 <= M <= 20 ) 张CD。每一张CD最多可以容纳 T ( 1 <= T <= 20 ) 分钟的音乐,一首歌不能分装在两张CD中。

  不巧你是一位古典音乐迷,不懂如何判定这些歌的艺术价值。于是你决定根据以下标准进行选择:

   (1)歌曲必须按照创作的时间顺序在CD盘上出现。

   (2)选中的歌曲数目尽可能地多。

Input

  第一行:三个整数N, T, M;

  第二行:N 个整数,分别表示每首歌的长度,按创作时间顺序排列。

Output

  一个整数,表示可以装进M张CD盘的乐曲的最大数目。

Sample Input

4 5 2  

4 3 4 2

Sample Output

  3

总结:虽然看上去还是二维背包问题,但在编时还是费了很多时间,原因是自己思路不清楚,又不能静下心来看例程。好在终于

看懂了例程,也把自己的完成了。

代码
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 int n,m,t,f[21][21][21];
5 int a[21];
6 int main(){
7 memset(f,0,sizeof(f));
8 FILE *in,*out;
9 in=fopen("input1.txt","r");
10 out=fopen("output.txt","w");
11 fscanf(in,"%d%d%d",&n,&t,&m);
12 int i,j,k;
13 for(i=1;i<=n;i++)
14 fscanf(in,"%d",&a[i]);
15 memset(f,0,sizeof(f));
16
17 for(i=1;i<=m;i++)
18 for(j=1;j<=n;j++)
19 for(k=0;k<=t;k++)
20 if(k>=a[j])
21 {
22 f[i][j][k]=f[i][j-1][k-a[j]]+1;
23 if(f[i][j][k]<f[i-1][j][t])
24 f[i][j][k]=f[i-1][j][t];
25 }
26 else
27 {
28 f[i][j][k]=f[i-1][j][t];
29 if(f[i][j][k]<f[i][j-1][k])
30 f[i][j][k]=f[i][j-1][k];
31 }
32
33
34 fprintf(out,"%d\n",f[m][n][t]);
35 fclose(in);
36 fclose(out);
37 return 0;
38 }
39

f[i][j][k]代表:前i张cd,前j首歌,第i张cd有k的空间可用,最多可录曲目数。a[j]为歌曲j的长度。它可由以下状态转移:

    if(k>=a[j])          f[i][j][k]=max{f[i][j-1][k-a[j]]+1,f[i-1][j][t]); 

    else                       f[i][j][k]=max{f[i-1][j][t],f[i][j-1][k]};

f[i][j-1][k-a[j]]+1—— 将歌曲j放入第i张cd的最多录制曲目数;

f[i-1][j][t]              ——不将歌曲j放入i盘,那么看前i-1张cd放j首歌曲的最多录制曲目数;      

f[i][j-1][k]             ——前i张cd放j-1首歌的最多录制曲目数。


  

 

 

posted @ 2010-07-28 18:18  Danty  阅读(353)  评论(0编辑  收藏  举报