题意:给n种硬币,每种硬币的面额为Ai,个数为Ci,问用这些硬币最多能凑出多少种不大于m的面额。
解法:男人八题之一……虽然我是个妹子但还是要做啊……_(:з」∠)_
看起来是个多重背包……然而算了复杂度之后……呵呵……
百度一下……被机智了一脸……
n层循环,dp[i][j]表示用前i个硬币是否能表示面额j,used[i][j]表示用前i个硬币表示面额j时用了多少个第i种硬币,显然i那维可以省略,used每次清空就可以了。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<limits.h> #include<time.h> #include<stdlib.h> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define LL long long using namespace std; struct node { int val, num; }coin[105]; bool dp[100005]; int used[100005]; int main() { int n, m; while(~scanf("%d%d", &n, &m) && !(n == 0 && m == 0)) { for(int i = 1; i <= n; i++) scanf("%d", &coin[i].val); for(int i = 1; i <= n; i++) scanf("%d", &coin[i].num); memset(dp, 0, sizeof dp); dp[0] = 1; int ans = 0; for(int i = 1; i <= n; i++) { memset(used, 0, sizeof used); for(int j = 1; j <= m; j++) { if(j - coin[i].val < 0) continue; if(dp[j]) continue; if(used[j - coin[i].val] >= coin[i].num) continue; if(!dp[j - coin[i].val]) continue; dp[j] = 1; used[j] = used[j - coin[i].val] + 1; ans++; } } printf("%d ", ans); } return 0; }