给定N种硬币,其中第 i 种硬币的面值为Ai,共有Ci个。
从中选出若干个硬币,把面值相加,若结果为S,则称“面值S能被拼成”。
求1~M之间能被拼成的面值有多少个。
输入格式
输入包含多组测试用例。
每组测试用例第一行包含两个整数N和M。
第二行包含2N个整数,分别表示A1,A2,…,AN和C1,C2,…,CN。
当输入用例N=0,M=0时,表示输入终止,且该用例无需处理。
输出格式
每组用例输出一个结果,每个结果占一行。
数据范围
1≤N≤100,
1≤M≤105,
1≤Ai≤105,
1≤Ci≤1000
输入用例:
3 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0
输出用例:
8
4
| 题意:如题 |
思路:
多重背包,看到数据范围肯定最多也就O(nm)的时间复杂度了。而且Ci的值很大,不能分散成一个个来当01背包。
用dp[j]表示能否凑到i这么大的面值。
我们用每个a[i].val(面值)去填 dp[j],那dp[j]能否被填好取决于dp[j-a[i].val]有没有被填好,同时在填那个位置的时候剩下来的a[i]要大于等于1 。
然后处理完之后遍历一遍1->m,累加计数即可。
AC代码:
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn

这是一道关于背包问题的动态规划(DP)题目,要求求解在给定的N种硬币面值和数量限制下,能拼成1到M之间面值的总数。输入包括硬币种类数N,最大面值M,以及每种硬币的面值Ai和数量Ci。由于Ci值较大,不适合用01背包的方法。解题思路是建立dp数组,通过遍历硬币面值和数量,更新dp状态,最后累加计数得出结果。
最低0.47元/天 解锁文章
357

被折叠的 条评论
为什么被折叠?



