CD(基础DP)
题面
题目大意
给一张容量为N的CD,以及若干首有特定时长的track,要求选出track使得CD被充分使用
题目分析
基础dp问题,做一个dp[ i ][ N ]的表,dp[ i ][ N ]表示选出前i个track时长不超过N的最大时长,照着白书模板打出代码即可。最后还原出路径则可以比较dp[ i ][ len ]与dp[ i-1 ][ len] 的大小关系,不相等表示第 i-1首track被选中,以此类推。
代码
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
#define mod 1000000007
using namespace std;
int dp[30][1000000];
int tracks[30];
int sign[30];
int N,number;
void solve()
{
for(int i=0;i<number;i++)
{
for(int j=0;j<=N;j++)
{
if(j<tracks[i]){
dp[i+1][j]=dp[i][j];
}else{
dp[i+1][j]=max(dp[i][j] , dp[i][ j-tracks[i] ]+tracks[i]);
}
}
}
int len=N;
for(int i=number;i>0;i--)
{
if(dp[i][len]!=dp[i-1][len])//还原路径
{
sign[i-1]=1;
len-=tracks[i-1];
}
}
}
int main()
{
while(~scanf("%d%d",&N,&number))
{
memset(dp,0,sizeof(dp));
memset(sign,0,sizeof(sign));
for(int i=0;i<number;i++)
{
scanf("%d",&tracks[i]);
}
solve();
for(int i=0;i<number;i++)
{
if(sign[i])printf("%d ",tracks[i]);
}
printf("sum:%d\n",dp[number][N]);
}
return 0;
}