hdu2126(求方案数的01背包)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2126
题意: n个物品,m元钱,每个物品最多买一次,问最多可以买几件物品,并且输出方案数。
分析:一看就想到01背包,不过得加一维来表示能买的物品件数。dp[i][j]表示在i元内至多能买j件物品。则状态转移方程为:dp[i][j]+=dp[i-a[k][j-1].
最后把在1~m元内买到的最大件数mx加起来就是题目所求。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <queue> #include <cstdlib> #include <stack> #include <vector> #include <set> #include <map> #define LL long long #define mod 1000000007 #define inf 0x3f3f3f3f #define N 1000010 #define clr(a) (memset(a,0,sizeof(a))) using namespace std; int dp[510][50],a[50]; int n,m; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]); clr(dp); dp[0][0]=1; int mx=0; for(int i=1;i<=n;i++) for(int j=m;j>=a[i];j--) { for(int k=n-1;k>=0;k--) { if(dp[j-a[i]][k])dp[j][k+1]+=dp[j-a[i]][k],mx=max(mx,k+1); } } if(mx==0) { puts("Sorry, you can't buy anything."); continue; } int ans=0; for(int i=0;i<=m;i++)ans+=dp[i][mx]; printf("You have %d selection(s) to buy with %d kind(s) of souvenirs.\n",ans,mx); } }