题目大意
给你一堆硬币,每种硬币价值不同数目不同,问能凑出小于m的多少种支付方案,
思路分析
显然是一个部分和问题,其实就是三重循环遍历,加上三个剪枝就够了,一道类似题的题解,三个剪枝看不懂的可以看上面的题解。
#include<iostream>
#include<string.h>
#include<string>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
#define MAX 100005
#define ll int
#define p pair<int,int>
#define inf 1111111111
ll dp[MAX];
ll A[MAX], C[1005];//value and num
int main() {
ll N, M;
while (cin >> N >> M && M + N > 0) {
for (int i = 0; i < N; i++) cin >> A[i];
for (int i = 0; i < N; i++) cin >> C[i];
memset(dp, 0, sizeof(dp));
ll maxp = 0, res = 0; dp[0] = 1;
for (int i = 0; i < N; i++) {
for (int j = maxp; j >= 0; j--) {//剪枝1
if (!dp[j])continue;
for (int k = 1; k <= C[i]; k++) {
if (j + k * A[i] > M)break;//剪枝2
if (dp[j + k * A[i]]) break;//剪枝3
dp[j + k * A[i]] = 1;
}
}
maxp += A[i] * C[i];
if (maxp > M)maxp = M;
}
for (int i = 1; i <= M; i++) if (dp[i])res++;
cout << res << endl;
}
}