传送门
题目描述
A thief made his way to a shop.
As usual he has his lucky knapsack with him. The knapsack can contain k objects. There are n kinds of products in the shop and an infinite number of products of each kind. The cost of one product of kind i is ai.
The thief is greedy, so he will take exactly k products (it‘s possible for some kinds to take several products of that kind).
Find all the possible total costs of products the thief can nick into his knapsack.
思路
首先只能想到这是一个完全背包,然后具体实现也不会,后来想了一会,发现可以用dp[i]来表示当总价值为i的时候,所用的物品的最小数目,由一个简单的贪心思想可以得到,显然相同的价值,用的物品越少,那么后面的发展机会就越大2333333
但是最后发现当下面这组数据时:
3 2
1 2 3
然后人就凉了,因为dp[3]跑出来是1,因为当时的dp的定义是选最小,这时就没有办法判断到底是否可以用2个物品达到价值为3。
然后就需要百度了qwq,先把价值由小到大进行排序,然后把所有的数都减去最小的那个数,这样当dp[i]的值比k小的时候,就可以加上任意多个第一个数,这样就可以处理这种情况了,要是不看题解我估计一辈子都想不到╮(╯▽╰)╭
代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; inline int cmp(int a,int b){ return a<b; } int dp[1000005]; int cos[1005]; int main(){ int n,k; cin>>n>>k; for(register int i=0;i<=1000004;i++){ dp[i]=99999999; } for(register int i=1;i<=n;i++){ cin>>cos[i]; } sort(cos+1,cos+n+1,cmp); dp[0]=0; for(register int i=1;i<=n;i++){ for(register int j=cos[i]-cos[1];j<=1000004;j++){ dp[j]=min(dp[j-(cos[i]-cos[1])]+1,dp[j]); } } //cout<<dp[6]<<endl; for(register int i=0;i<=1000004;i++){ //cout<<dp[i]<<endl; if(dp[i]<=k){ cout<<(k-dp[i])*cos[1]+dp[i]*cos[1]+i<<‘ ‘; } } }