题目描述 Description
你刚刚继承了流行的“破锣摇滚”乐队录制的尚未发表的N(1 <= N <= 20)首歌的版权。你打算从中精选一些歌曲,发行M(1 <= M <= 20)张CD。每一张CD最多可以容纳T(1 <= T <= 20)分钟的音乐,一首歌不能分装在两张CD中。
不巧你是一位古典音乐迷,不懂如何判定这些歌的艺术价值。于是你决定根据以下标准进行选择:
歌曲必须按照创作的时间顺序在CD盘上出现。
选中的歌曲数目尽可能地多。
输入描述 Input Description
第一行: 三个整数:N, T, M.
第二行: N个整数,分别表示每首歌的长度,按创作时间顺序排列。
输出描述 Output Description
一个整数,表示可以装进M张CD盘的乐曲的最大数目。
题解 Analysis
一开始想的就是dfs,然后就没有多考虑别的做法了。然而这是大犇眼中的水dp
设
f[i][j][k]
表示前
i
首歌曲装
f[i][j][k]=f[i−1][j][k]
不选
f[i][j][k]=max(f[i−1][j−1][t−T[i]]+1,f[i−1][j][k−T[i]]+1)
选
可以滚
然而我DFS 15MS AC
;P
\ps:
今天要死要活做出dp来了,状态没考虑全总是会只错一个点
代码 Code
#include <stdio.h>
using namespace std;
int t[21],n,m,k,ans=0;
void dfs(int dep,int grp,int cnt,int sum)
{
if (sum>m||grp>k||cnt+n+1-dep<ans)
return;
if (cnt>ans)
ans=cnt;
if (dep>=n+1)
return;
dfs(dep+1,grp,cnt,sum);
dfs(dep+1,grp+1,cnt+1,t[dep]);
if (grp)
dfs(dep+1,grp,cnt+1,sum+t[dep]);
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=n;i++)
scanf("%d",&t[i]);
dfs(1,0,0,0);
printf("%d\n",ans);
return 0;
}
/*
ID:wjp13241
PROG:rockers
LANG:C++
*/
#include <stdio.h>
using namespace std;
int f[2][21][21],t[21];
int max(int x,int y)
{
return x>y?x:y;
}
int main()
{
int n,T,m;
scanf("%d%d%d",&n,&T,&m);
for (int i=1;i<=n;i++)
scanf("%d",&t[i]);
int p=0;
for (int i=1;i<=n;i++)
{
p^=1;
for (int j=1;j<=m;j++)
for (int k=0;k<=T;k++)
{
if (T>=t[i])
f[p][j][k]=max(f[p][j][k],f[p^1][j-1][T-t[i]]+1);
if (k>=t[i])
f[p][j][k]=max(f[p][j][k],f[p^1][j][k-t[i]]+1);
f[p][j][k]=max(f[p][j][k],f[p^1][j][k]);
}
}
printf("%d\n",f[p][m][T]);
return 0;
}