http://poj.org/problem?id=1276
题意:银行里有一个取款机,cash表示应该取的钱数,接着有n种钞票,每种钞票的数量ni、面值di,求这个取款机最多可以取出多少钱。
思路:简单的多重背包。每种物品的花费和价值为同一属性。不要求装满背包。
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 100005;
const int INF = 0x3f3f3f3f;
int dp[N], V;
void ZeroOnePack(int cost, int weight)
{
for(int j = V; j >= cost; j--)
dp[j] = max(dp[j], dp[j-cost]+weight);
}
void CompletePack(int cost, int weight)
{
for(int j = cost; j <= V; j++)
dp[j] = max(dp[j], dp[j-cost]+weight);
}
void MultiplePack(int cost, int weight, int amount)
{
if(cost*amount>=V)
{
CompletePack(cost, weight);
return;
}
int k = 1;
while(k < amount)
{
ZeroOnePack(cost*k, weight*k);
amount-=k;//注意在前面
k=k*2;
}
ZeroOnePack(amount*cost, amount*weight);
}
int main()
{
// freopen("in.txt", "r", stdin);
int n;
int mon[N], amount[N];
while(~scanf("%d%d", &V, &n))
{
for(int i = 1; i <= n; i++)
scanf("%d%d", &amount[i], &mon[i]);
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++)
MultiplePack(mon[i], mon[i], amount[i]);
/* for(int i = 0; i <= V; i++)
printf("%d ", dp[i]);
printf("\n");*/
printf("%d\n", dp[V]);
}
return 0;
}