标签:
Description
Input
Output
Sample Input
735 3 4 125 6 5 3 350 633 4 500 30 6 100 1 5 0 1 735 0 0 3 10 100 10 50 10 10
Sample Output
735 630 0 0
Hint
题目大意:
有各种不同面值的货币,每种面值的货币有不同的数量,请找出利用这些货币可以凑成的最接近且小于等于给定的数字cash的金额。-----典型的多重背包
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #define N 600000 #define INF 0x3f3f3f3f #define LL long long using namespace std; int v[N], num[N], f[N]; int main() { int n, s; while(~scanf("%d%d", &s, &n)) { int i, j; for(i = 0; i < n; i++) scanf("%d%d", &num[i], &v[i]); if(s == 0 || n == 0)/*最后面Hint写的*/ { printf("0\n"); continue; } memset(f, 0, sizeof(f)); for(i = 0; i < n; i++) { if(v[i]*num[i] >= s)/*完全背包*/ { for(j = v[i]; j <= s; j++) f[j] = max(f[j], f[j - v[i]] + v[i]); } else { /*0-1背包*/ int k = 1; while(k < num[i])/*采用了二进制的思想*/ { for(j = s; j >= k * v[i]; j--) f[j] = max(f[j], f[j - k * v[i]] + k * v[i]); num[i] -= k; k <<= 1; } for(j = s; j >= num[i]*v[i]; j--) f[j] = max(f[j], f[j - num[i] * v[i]] + num[i] * v[i]); } } printf("%d\n", f[s]); } return 0; }
标签:
原文地址:http://www.cnblogs.com/yu0111/p/4727625.html