题目:点击打开链接
题意:
普通的01背包,有m元钱,最多有几种买的可能,按最大种类数买。
比如10元最多买4件物品,购买方式只有一种。7元最多买3件,有2种购买方式。
思路:
和2159二维完全背包类似,多了一个件数的隐含条件,需要加一维。
dp[j][k]表示花 j 元,恰好买k件物品是可行的,边界dp[0][0]=1,进行状态转移,可行就赋为1了,最后相同的k加起来即可。
k一定要倒着写,要知道二维的意义,每次j循环一次,dp[j][k],k从1到n只能加进去一个,当然在别的循环可能dp[7][3],dp[7][2]都被加进去,但同一循环不能被前面的影响,只能加一个。
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int a[35],dp[505][35];
int main(){
int t,n,m;
cin>>t;
while(t--){
memset(dp,0,sizeof(dp));
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
dp[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=m;j>=a[i];j--)
for(int k=n;k>=1;k--)
dp[j][k]=dp[j][k]+dp[j-a[i]][k-1];
int flg=0,ans=0;
for(int i=n;i>0;i--){
for(int j=m;j>=1;j--)
ans+=dp[j][i];
if(ans){
flg=1;
printf("You have %d selection(s) to buy with %d kind(s) of souvenirs.\n",ans,i);
break;
}
}
if(!flg)
printf("Sorry, you can't buy anything.\n");
}
return 0;
}