您的位置:首页 > 其它

POJ-1276(多重背包)

2014-06-12 19:20 323 查看
典型多重背包,和经典问题的不同点在于:

经典问题基本上都是问最少用多少钞票(最多用多少钞票)可以兑换出来

本题问的是用这些钞票在不超过取款金额的条件下最多可以取出多少现金

用状态dp[i] = 1表示在当前条件下可以取出数量为i的现金,dp[i] = 0表示不能取出,dp过程中即可找到可取现金的最大值



#include <stdio.h>
#include <string.h>
#define max(a,b) ((a) > (b) ? (a) : (b))

int money, cash;
int N, amount[10 + 1], value[10 + 1];
char dp[100000 + 1];

void zeroOnePack(int v)
{
int i = money;
for(; i >= v; --i)
if(dp[i] |= dp[i - v]) cash = max(cash, i);
}
void completePack(int v)
{
int i = v;
for(; i <= money; ++i)
if(dp[i] |= dp[i - v]) cash = max(cash, i);
}
void multiPack(int v, int c)
{
if(v * c >= money){
completePack(v);
return;
}
int k = 1;
for(; k < c; k <<= 1){
zeroOnePack(v * k);
c -= k;
}
zeroOnePack(v * c);
}

int main()
{
int i, total;
while(scanf("%d %d", &money, &N) == 2){
total = 0;
/* input */
for(i = 0; i < N; ++i){
scanf("%d %d", &amount[i], &value[i]);
total += amount[i] * value[i];
}
/* judge */
if(money == 0 || N == 0) puts("0");
else if(total <= money) printf("%d\n", total);
else{
/* initialize */
memset(dp, 0, money + 1);
dp[0] = 1;
cash = 0;
/* multi-pack*/
for(i = 0; i < N; ++i){
if(amount[i]) multiPack(value[i], amount[i]);
}
/* print result */
printf("%d\n", cash);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: