POJ 1276 Cash Machine (multiple backpack)
http://poj.org/problem?id=1276
Test Instructions :
There are n currencies, with denominations and quantities of val[i] and num[i] respectively. Now give an M-value, and ask you what is the largest and not more than m of the amount that you can make up of the above currency?
Analysis :
Obvious multi-knapsack problem.
Dp[i][j]==x that the maximum value of the money in the <=j denomination of the former I currency can be x.
Initialize: DP is full 0.
We carry out the sub-situation of the article I:
If val[i]*num[i]>=m, then do a full backpack for the item.
If val[i]*num[i]<m, re-categorize the item and make multiple 01 backpacks.
Final request: Dp[n][m].
The program is implemented in reverse order with a scrolling array, so DP is only [j] one dimension.
AC Code :
#include <cstdio> #include <cstring> #include <algorithm>using namespace std;const int maxn=100000+5; int m;//maximum amount int n;//currency number int val[1000+5];//currency value int num[1000+5];//currency number int DP[MAXN];//1 times 01 backpack process void Zero_one_pack (int Cost) {for (int i=m;i>=cost;i--) dp[i] = max (Dp[i], dp[i-cost]+cost);} 1 times full backpack void complete_pack (int cost) {for (int i=cost;i<=m;i++) dp[i] = max (Dp[i], dp[i-cost]+cost);} 1 times multiple backpack void multiply_pack (int cost,int sum) {if (cost*sum>=m) {complete_pack (cost); return; } int k=1; while (k<sum) {zero_one_pack (cost*k); Sum-=k; k*=2; } zero_one_pack (cost*sum);} int main () {while (scanf ("%d%d", &m,&n) ==2) {//Read input for (int i=1;i<=n;i++) scanf (" %d%d ", &num[i],&val[i]); Recursive + output memset (dp,0,sizeof (DP)); for (int i=1;i<=n;i++) Multiply_pack (Val[i],num[i]); printf ("%d\n", Dp[m]); } return 0;}
POJ 1276 Cash Machine (multiple backpack)