经典的01背包问题。
这里的每个物品的体积跟价值都是相等。
状态转移方程:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-vp[i]]+vp[i])
dp[i][j]表示前i首歌所占录音带的最大长度。
最后要求输出一个最优解。
有两种办法。第一种办法是开一个数组vis[][]存下每次使用的歌,最后从vis[N][T]开始从后往前递推寻找每次使用的歌。
第二种办法是比较dp[i][j]与dp[i-1][j]的大小,如果dp[i][j]>dp[i-1][j]说明使用了第i首歌,否则说明没使用,由也是dp[N][T]开始从后往前寻找。
我这里用了第二种办法。
如果要求正序输出最优解,可以使用递归。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int main()
{
int T,N;
while(scanf("%d",&T)!=EOF)
{
int vp[30]={0};
int dp[25][1500]={0};
scanf("%d",&N);
for(int i=1;i<=N;++i) scanf("%d",&vp[i]);
for(int i=1;i<=N;++i)
for(int j=1;j<=T;++j)
{
if(j>=vp[i])
{
if(dp[i-1][j]<dp[i-1][j-vp[i]]+vp[i])
dp[i][j]=dp[i-1][j-vp[i]]+vp[i];
else dp[i][j]=dp[i-1][j];
}
else dp[i][j]=dp[i-1][j];
}
int m=T;
for(int i=N;i>0;i--)
if(dp[i][m]>dp[i-1][m])
{
printf("%d ",vp[i]);
m-=vp[i];
}
printf("sum:%d\n",dp[N][T]);
}
return 0;
}