题意:给你一堆钱,有许多面值,每种若干张,请找出利用这些钱可以凑成的最接近且小于给定的数字的数额。。
思路:多重背包。。。
1 /* 2 State:Accepted 3 Time:2013.3.3 4 */ 5 #include <iostream> 6 #include <cstring> 7 #include <string> 8 #include <cstdlib> 9 #include <cstdio> 10 #include <cmath> 11 #include <algorithm> 12 #include <vector> 13 #define CLR(NAME) memset(NAME , 0 , sizeof(NAME)) 14 15 const int maxm = 100010; 16 int f[maxm] , fnum[maxm] , num[150] , d[150] , m ,n; 17 18 void dp(){ 19 CLR(f); 20 scanf("%d",&n); 21 for (int i = 1; i <= n ; ++i) 22 scanf("%d%d",&num[i] , &d[i]); 23 if (n == 0 || m == 0){ 24 printf("0\n"); 25 return; 26 } 27 28 f[0] = 1; 29 for (int i = 1; i <= n; ++i){ 30 memset(fnum , 1000000 , sizeof(fnum) ); 31 for (int j = m; j >= 0; --j) 32 if (f[j]){ 33 for (int k = 0; j + d[i] * k <= m && k <= num[i] ; ++k) 34 if (f[j + d[i] * k] && k >= fnum[j + d[i] *k]) break; 35 else { 36 f[j + d[i] * k] = 1; 37 fnum[j + d[i] *k] = k; 38 } 39 } 40 } 41 for (int i = m ; i >= 0; --i) 42 if (f[i]) { printf("%d\n", i); return; } 43 } 44 45 int main(){ 46 freopen("poj1276.in","r",stdin); 47 freopen("poj1276.out","w",stdout); 48 while (scanf("%d",&m)!= EOF){ 49 dp(); 50 } 51 }