题解:本题主要考察DP
简要题意:
n
(
1
<
=
n
<
=
20
)
n(1<=n<=20)
n(1<=n<=20)首歌,每首歌
t
i
m
e
i
time_i
timei分钟,有
m
(
1
<
=
n
<
=
20
)
m(1<=n<=20)
m(1<=n<=20)张CD,每一张CD最多可以容纳
t
(
1
<
=
t
<
=
20
)
t(1<=t<=20)
t(1<=t<=20)分钟的音乐。歌曲必须按照创作的时间顺序在所有的CD上,求选中的歌曲数目最多的数量。
1.dp:本题可看出有三种状态:设
f
[
i
]
[
j
]
[
k
]
f[i][j][k]
f[i][j][k]表示
i
i
i首歌,
j
j
j张CD,该CD的容量为
k
k
k分钟
1.歌曲不装入CD:不变;
2.歌曲装入本张CD上:
f
[
i
−
1
]
[
j
]
[
k
−
t
i
m
e
[
i
]
]
+
1
)
f[i-1][j][k-time[i]]+1)
f[i−1][j][k−time[i]]+1);
3.用一张新唱片:
f
[
i
−
1
]
[
j
−
1
]
[
t
]
+
1
f[i-1][j-1][t]+1
f[i−1][j−1][t]+1;
可以看出其实就是01背包的变形(二维背包),所以就可以降一维,方程为:
f
[
j
]
[
k
]
=
m
a
x
(
f
[
j
]
[
k
]
,
f
[
j
−
1
]
[
t
]
+
1
,
f
[
j
]
[
k
−
t
i
m
e
[
i
]
]
+
1
)
;
f[j][k]=max(f[j][k],f[j-1][t]+1,f[j][k-time[i]]+1);
f[j][k]=max(f[j][k],f[j−1][t]+1,f[j][k−time[i]]+1);
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
int timme[600],f[99][99];
int n,m,t,maxn;
int main()
{
cin>>n>>t>>m;
for(int i=1;i<=n;i++)cin>>timme[i];
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--)
for(int k=t;k>=timme[i];k--)
f[j][k]=max(f[j][k],max(f[j-1][t]+1,f[j][k-timme[i]]+1));
for(int i=1;i<=m;i++)
for(int j=1;j<=t;j++)
maxn=max(maxn,f[i][j]);
cout<<maxn<<endl;
return 0;
}