题目
Description
西瓜的表弟小西瓜生病住院了,西瓜想去买一个水果篮子探望他。水果店里面有很多种类的水果篮子,价格相同,但是水果的搭配各不相同。西瓜突然想到了一个问题,现在水果店里面有这么N种水果,第i个水果单价是Pi元,西瓜手上有M元钱(钱不一定要花完,但也不能什么水果都没有),一共有几种搭配水果篮子的方法呢。
Input
题目包含多组输入,EOF结束,数据最多不超过100组,对于每组数据,包含两行,第一行是两个整数N,M,表示水果的总数和西瓜手里的钱数。第二行包含N个整数,表示每种水果的单价。
1 <= N <= 10, 1 <= M <= 200, 1 <= Pi <= MOutput
对于每组输入,输出一行,表示有多少种搭配水果篮子的方法。
Sample Input
2 10
3 4
9 100
5 6 9 13 4 5 3 9 8Sample Output
7
1954041
题解
背包问题的计数问题
dp[i][j]
表示前i件水果在钱数为j时的可行的选择种类数目
则有 d[i][j] = (d[i-1][j] + 1) + d[i][j-price[i]]
分别代表买和不买这个物品
初始状态为dp[0][0] = 0
(什么都买不了)
压缩成一维数组 d[j] += ((j - price[i] >= 0) ? (d[j - price[i]] + 1) : 0);
代码
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <vector> #include <list> #include <stack> using namespace std; #define REP(n) for(int o=0;o<n;o++) int N,M;//N水果数 M钱数 const int maxn = 15; const int maxm = 205; long long d[maxm]; int price[maxn]; bool Do() { if(scanf("%d%d",&N,&M) == EOF) return false; REP(N) scanf("%d",&price[o + 1]); memset(d,0,sizeof(d)); for(int i = 1;i <= N;i++) for(int j = 1;j <= M;j++) d[j] += ((j - price[i] >= 0) ? (d[j - price[i]] + 1) : 0); printf("%lld\n",d[M]); return true; } int main() { while(Do()); return 0; }