题意:给n个数,从中选k个(可以重复选)加起来,问最后有多少种不同的价值
思路:看起来很像一个多重背包,然而要准确的选到k个是不简单的,比如1 2 3 4 5,k=3,那么dp[6]=2,可是显然6也是可以由1,2,3来组成,所以直接多重背包会丢失解,解决方法是每个元素都减去a[1],令dp[i]为选了dp[i]个数价值为i,那么如果只用了k-2就凑成i,那么剩下的2个可以由a[1]来补上去,那么就恰好符合了题目要求的选k个数了。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3+5;
int n,k,a[maxn],dp[maxn*maxn];
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
n=unique(a+1,a+1+n)-(a+1);
for(int i=2;i<=n;i++)
a[i]=a[i]-a[1];
for(int i=1;i<=k*a[n];i++)
dp[i]=k+1;
for(int i=2;i<=n;i++)
for(int j=a[i];j<=k*a[i];j++)
dp[j]=min(dp[j],dp[j-a[i]]+1);
for(int i=0;i<=k*a[n];i++)
if(dp[i]<=k)
printf("%d ",a[1]*k+i);
return 0;
}