分析:题目是一个01背包问题。但是增加了路径输出。
由于路径,所以才有二维递推的形式。
dp[i,j]=max{ dp[i-1,j], dp[i-1,j-m[i]]+m[i]}
在输出集合的时候,如果dp[i,j]==dp[i-1,j],那么表明第i个物品是没有选入的。
采用的逆推的形式。
#include<stdio.h>
#include<string.h>
int C,dp[21][100000];
int main()
{
int N,m[22];
while (scanf("%d%d",&C,&N)!=EOF)
{
for(int i=1;i<=N;i++)
scanf("%d",&m[i]);
for(int j=0;j<=C;j++)
{
if(j>=m[1]) dp[1][j]=m[1];
else dp[1][j]=0;
}
//递推
for(int i=2;i<=N;i++)
for(int j=0;j<=C;j++)
{
if(j>=m[i]&&dp[i-1][j]<dp[i-1][j-m[i]]+m[i])
dp[i][j]=dp[i-1][j-m[i]]+m[i];
else
dp[i][j]=dp[i-1][j];
}
//输出集合,倒推
int i=N,j=C;
while(i)
{
if(dp[i-1][j]!=dp[i][j])
{
printf("%d ",m[i]);
j-=m[i];
}
i--;
}
printf("sum:%d
",dp[N][C]);
}
return 0;
}