思路:显然的思路是前i个物品选j个花费k元的次数。
dp[i][j][k] = dp[i - 1][j][k] + dp[i - 1][j - 1][k - v[i]];
由上面的转移方程可以看出来,可以去掉一维,就是dp[j][k] = dp[j - 1][k - v[i]] + dp[j][k];
/***************************************** Author :Crazy_AC(JamesQi) Time :2015 File Name : *****************************************/ // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #include <limits.h> using namespace std; #define MEM(a,b) memset(a,b,sizeof a) typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; inline int Readint(){ char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0; while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); } return x; } int n,m,t; int a[35], dp[35][510]; int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); memset(dp, 0,sizeof dp); for (int i = 1;i <= n;i++) scanf("%d",&a[i]); dp[0][0] = 1; for (int i = 1;i <= n;i++){ for (int j = n;j >= 1;--j){ for (int k = m;k >= a[i];--k) dp[j][k] += dp[j - 1][k - a[i]]; } } int ans; bool flag=false; for (int j = n;j >= 1;--j){ ans = 0; for (int k = m;k >= 0;k--) ans += dp[j][k]; if (ans){ printf("You have %d selection(s) to buy with %d kind(s) of souvenirs.\n", ans, j); flag = true; break; } } if (!flag) printf("Sorry, you can't buy anything.\n"); } return 0; }