http://poj.org/problem?id=1787
题意:查理想买咖啡,咖啡销售机只支持三种硬币,分别是1分、5分、10分、15分。然后给出查理拥有的四种硬币的个数,求查理最多可以消耗多少硬币,可以正好买到咖啡而且不需要找钱。
思路:给出每种物品的个数,即为多重背包。不过这题要求的是装满情况下的最多数量,那么数量即为价值。最后要求把每种硬币的数量分别输出,难点就在路径的记录。看的别人的思想,用一个二维数组存储路径,与dp值的更新同步,这种思想值得学习,需要多看!
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 10005;
const int INF = 0x3f3f3f3f;
int dp[N], V, path[N][4], num[10];
void ZeroOnePack(int cost, int weight, int id, int num)
{
for(int j = V; j >= cost; j--)
{
//放入物品后容量为j的最大价值大于不放的最大价值而且前几种物品放入容量为j的价值合法则更新
if(dp[j-cost]+weight>dp[j] && dp[j-cost]!=-INF)
{
dp[j] = dp[j-cost]+weight;
for(int i = 1; i <= 4; i++)
{
//一旦某物被选上,同时所有id的路径都更新,防止更新当前路径时丢掉别的路径
path[j][i] = path[j-cost][i];
}
path[j][id] = path[j][id]+num;
}
// dp[j] = max(dp[j], dp[j-cost]+weight);
}
}
void CompletePack(int cost, int weight, int id)
{
for(int j = cost; j <= V; j++)
{
if(dp[j-cost]+weight>dp[j] && dp[j-cost]!=-INF)
{
dp[j] = dp[j-cost]+weight;
for(int i = 1; i <= 4; i++)
{
path[j][i] = path[j-cost][i];
}
path[j][id] = path[j][id]+1;
}
}
}
void MultiplePack(int cost, int weight, int amount, int id)
{
if(cost*amount>=V)
{
CompletePack(cost, weight, id);
return;
}
int k = 1;
while(k < amount)
{
ZeroOnePack(cost*k, weight*k, id, k);
amount-=k;//注意在前面
k=k*2;
}
ZeroOnePack(amount*cost, amount*weight, id, amount);
}
int main()
{
// freopen("in.txt", "r", stdin);
int mon[N], amount[N];
num[1] = 1;
num[2] = 5;
num[3] = 10;
num[4] = 25;
while(~scanf("%d%d%d%d%d", &V, &amount[1], &amount[2], &amount[3], &amount[4]))
{
if(V==0 && amount[1]==0 && amount[2]==0 && amount[3]==0 && amount[4]==0) break;
dp[0] = 0;//装满
for(int i = 1; i < N; i++)
dp[i] = -INF;
memset(path, 0, sizeof(path));
for(int i = 1; i <= 4; i++)
MultiplePack(num[i], 1, amount[i], i);
/* for(int i = 1; i <= V; i++)
{
for(int j = 1; j <= 4; j++)
printf("%d ", path[i][j]);
printf("\n");
}
printf("\n");*/
if(dp[V] != -INF) printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n", path[V][1], path[V][2], path[V][3], path[V][4]);
else printf("Charlie cannot buy coffee.\n");
}
return 0;
}