【POJ - 1742】Coins (多重背包)
Coins
直接翻译了
Descriptions
给出硬币面额及每种硬币的个数,求从1到m能凑出面额的个数。
Input
多组数据,每组数据前两个数字为n,m。n表示硬币种类数,m为最大面额,之后前n个数为每种硬币的面额,后n个数为相应每种硬币的个数。 (n<=100,m<=100000,面额<=100000,每种个数<=1000)
Output
对于每个测试用例,在单行上输出答案。
Sample Input
3 10 1 2 4 2 1 1 2 5 1 4 2 1 0 0
Sample Output
8 4
题目链接
https://vjudge.net/problem/POJ-1742
设d[i][j]——前i种硬币,凑成总值j时,第i种硬币所剩余的个数。
默认d[i][j] = -1,代表无法凑成总值j
转移方程为,若d[i-1][j]≥0,代表前i-1种已能够凑成j,那么就不必花费第i种硬币,所以d[i][j] = c[i]
否则就看d[i][j-v[i]]的值,显然如果j < v[i],那么d[i][j] = -1,否则d[i][j-a[i]] ≤ 0,代表此刻第i种硬币已使用完了,所以自然d[i][j] = -1;
否则,d[i][j] = d[i][j-v[i]]-1;
AC代码
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string>1 #include <cstring> #include <map> #include <stack> #include <set> #include <sstream> #define IOS ios_base::sync_with_stdio(0); cin.tie(0); #define Mod 1000000007 #define eps 1e-6 #define ll long long #define INF 0x3f3f3f3f #define MEM(x,y) memset(x,y,sizeof(x)) #define Maxn 1000005 using namespace std; int n,m; int dp[Maxn]; int v[Maxn]; int c[Maxn]; bool cmp(int x) { return x>=0; } int main() { while(cin>>n>>m,n+m) { for(int i=0; i<n; i++) cin>>v[i]; for(int i=0; i<n; i++) cin>>c[i]; MEM(dp,-1); dp[0]=0; for(int i=0; i<n; i++) { for(int j=0; j<=m; j++) { if(dp[j]>=0) dp[j]=c[i]; else if(j<v[i]||dp[j-v[i]]<=0) dp[j]=-1; else dp[j]=dp[j-v[i]]-1; } } cout<<count_if(dp+1,dp+1+m,cmp)<<endl;//搜索dp数组中大于等于0的个数 } return 0; }