Poj 1276 Cash Machine (DP_背包)

题目链接:http://poj.org/problem?id=1276


题目大意:一台免费的现金输出机器,先输入一个金额sum,里面有n种货币,面值为val[i],数量为num[i],问最多输出多少现金?(当然输出越多越好,免费的!)


解题思路:由于sum为10万,num[i]小于1000,怕用暴力地超时,所以用了多重背包来解:sum是背包容量,n种货币就是n个物品,然后经过二进制处理吧每种物品转化为x件物品,转化完成后可以用01背包解。状态转移方程:if (dp[j-cost[i]) dp[j] = 1; (cost[i]表示二进制处理后的第i件物品),复杂度O(V*sum(log(num[i]))。做完这题去看了下别人的解题报告,发现十分暴力的O(V*N*sum(num[i])竟然可以过,要不要这么暴力啊!poj的数据敢不敢再水点!


测试数据:

735 3  4 125  6 5  3 350

633 4  500 30  6 100  1 5  0 1


代码:

#include <stdio.h>
#include <string.h>
#define MAX 110000


int tot,val[MAX],num[MAX];
int sum,n,cost[MAX],dp[MAX];


int main()
{
	int i,j,k,t;


	while (scanf("%d%d",&sum,&n) != EOF) {

		for (i = 1; i <= n; ++i)
			scanf("%d%d",&num[i],&val[i]);


		memset(dp,0,sizeof(dp));
		for (tot = i = 1; i <= n; ++i) {

			for (k = 0; (1<<k) <= num[i]; ++k)
				cost[tot++] = (1<<k) * val[i],num[i] -= (1<<k);
			cost[tot++] = num[i] * val[i];
		}


		for (dp[0] = i = 1; i < tot; ++i)
			for (j = sum; j >= cost[i]; --j)
				if (dp[j-cost[i]]) dp[j] = 1;
		for (i = sum; i >= 0 && !dp[i]; --i);
		printf("%d\n",i);
	}
}

本文ZeroClock原创,但可以转载,因为我们是兄弟。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值