题目大意:从n种物品里面(每种无限个)选k个物品,打印所有可能的价值
解析:每种无限个,所以可以想到完全背包,但是直接dp,恰好k次是很难控制的
所以我们可以让 每一个物品的价值减去他们的最小值,这样最小值那个物品的价值就变成了0,所以我们可以枚举每个价值(最大1e6),如果组成这个价值的件数小于等于k,剩下的就可以用最小值物品的0补齐,(这个价值+k*最小值)就是可以生成的价值
所以dp[j]表示的是(j+最小值*k)的价值是否存在
具体代码还有注释
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;
const int N=1e6+100;
int arr[N],dp[N];
int main()
{
ios::sync_with_stdio(false);
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++)
cin>>arr[i];
sort(arr,arr+n);
int t=arr[0];
for(int i=0;i<n;i++)//每个都减去最小值
arr[i]-=t;
for(int i=0;i<=N;i++)
dp[i]=inf;
dp[0]=0;//这里表示的是0+k*t 是一定存在的,初始化为0
for(int j=0;j<N;j++)
for(int i=0;i<n;i++)//这里正序逆序都是可以的,只是一种存在情况
if(j>=arr[i])
dp[j]=min(dp[j],dp[j-arr[i]]+1);
for(int j=0;j<N;j++)
if(dp[j]<=k)
cout<<j+t*k<<' ';
cout<<endl;
return 0;
}