1742:Coins:部分和问题变形:简单dp+三剪枝(部分和问题通用)

题目大意

题目传送门

给你一堆硬币,每种硬币价值不同数目不同,问能凑出小于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;
	}
}
发布了211 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/csyifanZhang/article/details/105362319