描述
你刚刚继承了流行的“破锣摇滚”乐队录制的尚未发表的N(1 <= N <= 20)首歌的版权。你打算从中精选一些歌曲,发行M(1 <= M <= 20)张CD。每一张CD最多可以容纳T(1 <= T <= 20)分钟的音乐,一首歌不能分装在两张CD中。
不巧你是一位古典音乐迷,不懂如何判定这些歌的艺术价值。于是你决定根据以下标准进行选择:
1.歌曲必须按照创作的时间顺序在CD盘上出现。
2.选中的歌曲数目尽可能地多。
3.不仅同光盘上的歌曲写入时间要按顺序,前一张光盘上的歌曲不能比后一张歌曲写入时间要晚。
格式
PROGRAM NAME: rockers
INPUT FORMAT:
(file rockers.in)
第一行: 三个整数:N, T, M.
第二行: N个整数,分别表示每首歌的长度,按创作时间顺序排列。
OUTPUT FORMAT:
(file rockers.out)
一个整数,表示可以装进M张CD盘的乐曲的最大数目。
SAMPLE INPUT
4 5 2
4 3 4 2
SAMPLE OUTPUT
3
分析:
01背包模型,f[i][j]=Max{f[i-1][j],f[i-1][j-a[i]]+1},当然还要加上1维表示当前在第几个CD,即f[i][j][k]表示到第i首歌用到第j个CD,最后一个CD还剩k分钟能装的最多的歌曲。
状态转移方程还是很容易想出来的,只是细节处理需要仔细点。
USER: Zhipeng ZHANG [138_3531]
TASK: rockers
LANG: C++
Compiling...
Compile: OK
Executing...
Test 1: TEST OK [0.000 secs, 3212 KB]
Test 2: TEST OK [0.000 secs, 3212 KB]
Test 3: TEST OK [0.011 secs, 3212 KB]
Test 4: TEST OK [0.000 secs, 3212 KB]
Test 5: TEST OK [0.000 secs, 3212 KB]
Test 6: TEST OK [0.000 secs, 3212 KB]
Test 7: TEST OK [0.000 secs, 3212 KB]
Test 8: TEST OK [0.011 secs, 3212 KB]
Test 9: TEST OK [0.011 secs, 3212 KB]
Test 10: TEST OK [0.011 secs, 3212 KB]
Test 11: TEST OK [0.011 secs, 3212 KB]
Test 12: TEST OK [0.011 secs, 3212 KB]
All tests OK.
Your program ('rockers') produced all correct answers! This is your submission #9 for this problem. Congratulations!
/* ID:138_3531 LANG:C++ TASK: rockers */ #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <string> using namespace std; int Max(int a,int b) { return a>b?a:b; } int main() { freopen("rockers.in","r",stdin); freopen("rockers.out","w",stdout); int n,m,t; int a[25]; int f[25][25][25]; memset(f,0,sizeof(f)); cin>>n>>t>>m; for (int i=1;i<=n;i++) cin>>a[i]; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) for (int k=0;k<=t;k++) //细节,k=0 { f[i][j][k]=f[i-1][j][k]; if (t>=a[i]) { if (k>=a[i]) f[i][j][k]=Max(f[i][j][k],f[i-1][j][k-a[i]]+1); if (j>1) //这里很重要,还是一步一步调试才发现错的 f[i][j][k]=Max(f[i][j][k],f[i-1][j-1][t-a[i]]+1); } } cout<<f[n][m][t]<<endl; return 0; }