思路 :严格的控制好k的这个数量,这就是个裸完全背包问题.(复杂度最极端会到1e9)
他们随意原来随意组合的方案,与他们都减去 最小的 一个 a[ i ] 组合的方案数目是不会改变的
那么我们就 dp [ i ]表示 i 这个价格需要的最少 个数。 这样求最小个数保证不会漏解
然后 如果这个 i 能通过 1 - k 个物品组合出来,那么 一定能通过k 个物品组合出 i + k * a [ 1 ].
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 0x3f3f3f3f #define maxn 1234567 int n,k,dp[maxn],a[maxn]; int v[maxn],mi,sum,id,base; map<int,bool>vis; vector<int>ans; int main() { scanf("%d%d",&n,&k); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); if(vis[a[i]]==0) { vis[a[i]]=1; v[++id]=a[i]; } } sort(v+1,v+1+id); base=v[1]*k; for(int i=2; i<=id; i++) v[i]-=v[1]; sum=v[id]*k; memset(dp,inf,sizeof(dp)); dp[0]=0; for(int i=2; i<=id; i++) for(int j=v[i]; j<=sum; j++) dp[j]=min(dp[j],dp[j-v[i]]+1); for(int i=0; i<=sum; i++) { if(dp[i]>k)continue; ans.push_back(i+base); } int len=ans.size(); for(int i=0; i<len; i++) { printf("%d",ans[i]); if(i<len-1)printf(" "); else printf("\n"); } return 0; }