POJ 3260 The Fewest Coins(多重背包+全然背包)
POJ 3260 The Fewest Coins(多重背包+全然背包)
http://poj.org/problem?id=3260
题意:
John要去买价值为m的商品. 如今的货币系统有n种货币,相应面值为val[1],val[2]…val[n]. 然后他身上每种货币有num[i]个. John必须付给售货员>=m的金钱, 然后售货员会用最少的货币数量找钱给John.
问你John的交易过程中, 他给售货员的货币数目+售货员找钱给他的货币数目 的和最小值是多少?
分析:
本题与POJ 1252类型:
http://blog.csdn.net/u013480600/article/details/40454963
如果John付款总额为S时的货币数目为T1, 售货员找钱 (S-m) 的货币数目为T2. 我们要使得T1+T2最小, 那么自然T1和T2也必须分别是最小的(即T1是当John付款正好S时,最少须要多少张货币.
T2是当售货员正好找钱S-m时,最少须要多少张货币.).
John给的钱肯定>=m, 可是究竟最大多大呢? 假设我们直接求John的全部金钱总和, 然后再DP, 肯定超时. 这个up_bound (即john最多给售货员的钱数) 能够简单设置一个大数值就可以. 网上有个证明(这个证明我也有点不明确):
John的付款数最多为maxv*maxv+m
证明例如以下:
假设John的付款数大于了maxv*maxv+m,即付硬币的数目大于了maxv,依据鸽笼原理。至少有两个的和对maxv取模的值相等(这个意思应该是:至少maxv+1个硬币对maxv求余,然后余数属于[0,maxv-1]范围,肯定有至少两个硬币的余数同样的),也就是说。这部分硬币可以用更少的maxv来取代(这句话我不理解)。
证毕。
第一个问题是一个多重背包问题.
令dp[i][j]==x 表示当John用前i种货币组成j元钱时, 最少须要x张货币.
初始化: dp全为INF(无穷大), 且dp[0][0]=0.
对于每种货币, 我们分情况对它进行处理:
1. 假设val[i]*num[i]>=up_bound时, 做一次全然背包.
2. 假设val[i]*num[i]<up_bound时, 做多次01背包.
终于所求: dp[n][i] 当中i属于[m, up_bound].
第2个问题是一个全然背包问题.
令dp2[i][j]==x 表示售货员用前i种硬币组成j元钱时, 最少须要x张货币.
初始化: dp2全为INF(无穷大), 且dp2[0][0]=0.
状态转移: dp2[i][j] = max( dp2[i-1][j] , dp2[i][j-val[i]]+1 )
终于所求: dp2[n][i] 当中i属于[m, up_bound].
终于合并问题1和问题2的解, 我们枚举i从m到up_bound, 找出dp[i]+dp2[i-m]的最小值就可以.
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 1e9 int n;//n种硬币
int m;//购买商品的价值
int up_bound;//DP价值上界
int val[100+5];//每种硬币价值
int num[100+5];//每种硬币数目
int dp[55555]; //多重背包
int dp2[55555];//全然背包 //1次01背包
void ZERO_ONE_PACK(int *dp,int cost,int sum)
{
for(int i=up_bound;i>=cost;i--)
dp[i] = min(dp[i], dp[i-cost]+sum);//注意这里是+sum
} //1次全然背包
void COMPLETE_PACK(int *dp,int cost)
{
for(int i=cost;i<=up_bound;i++)
dp[i] = min(dp[i], dp[i-cost]+1);
} //1次多重背包
void MULTIPLY_PACK(int *dp,int cost,int sum)
{
if(cost*sum>=up_bound)
{
COMPLETE_PACK(dp,cost);
return ;
} int k=1;
while(k<sum)
{
ZERO_ONE_PACK(dp,cost*k,k);
sum -=k;
k *=2;
}
ZERO_ONE_PACK(dp,cost*sum,sum); } int main()
{
while(scanf("%d%d",&n,&m)==2)
{
//读取输入+计算上界
int max_val=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
max_val= max(max_val,val[i]);
}
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
up_bound=max_val*max_val+m;//上界 //初始化dp和dp2
for(int i=1;i<=up_bound;i++)
dp[i]=dp2[i]=INF;
dp[0]=dp2[0]=0; //递推过程
for(int i=1;i<=n;i++)
{
MULTIPLY_PACK(dp,val[i],num[i]);
COMPLETE_PACK(dp2,val[i]);
} //统计结果
int ans=INF;
for(int i=m;i<=up_bound;i++)
ans= min(ans, dp[i]+dp2[i-m]);
printf("%d\n",ans==INF?-1:ans);
}
return 0;
}
POJ 3260 The Fewest Coins(多重背包+全然背包)的更多相关文章
- POJ 3260 The Fewest Coins(多重背包问题, 找零问题, 二次DP)
Q: 既是多重背包, 还是找零问题, 怎么处理? A: 题意理解有误, 店主支付的硬币没有限制, 不占额度, 所以此题不比 1252 难多少 Description Farmer John has g ...
- POJ 3260 The Fewest Coins(完全背包+多重背包=混合背包)
题目代号:POJ 3260 题目链接:http://poj.org/problem?id=3260 The Fewest Coins Time Limit: 2000MS Memory Limit: ...
- POJ 3260 The Fewest Coins 最少硬币个数(完全背包+多重背包,混合型)
题意:FJ身上有各种硬币,但是要买m元的东西,想用最少的硬币个数去买,且找回的硬币数量也是最少(老板会按照最少的量自动找钱),即掏出的硬币和收到的硬币个数最少. 思路:老板会自动找钱,且按最少的找,硬 ...
- POJ 3260 The Fewest Coins(背包问题)
[题目链接] http://poj.org/problem?id=3260 [题目大意] 给出你拥有的货币种类和每种的数量,商店拥有的货币数量是无限的, 问你买一个价值为m的物品,最少的货币流通数量为 ...
- poj 3260 The Fewest Coins
// 转载自http://blog.163.com/benz_/blog/static/18684203020115721917109/算法不难看出,就是一个无限背包+多重背包.问题在于背包的范围.设 ...
- HDU 3591 The trouble of Xiaoqian(多重背包+全然背包)
HDU 3591 The trouble of Xiaoqian(多重背包+全然背包) pid=3591">http://acm.hdu.edu.cn/showproblem.php? ...
- POJ3260——The Fewest Coins(多重背包+完全背包)
The Fewest Coins DescriptionFarmer John has gone to town to buy some farm supplies. Being a very eff ...
- hdu3591The trouble of Xiaoqian 多重背包+全然背包
//给出Xiaoqian的钱币的价值和其身上有的每种钱的个数 //商家的每种钱的个数是无穷,xiaoqian一次最多付20000 //问如何付钱交易中钱币的个数最少 //Xiaoqian是多重背包 / ...
- DP专题·三(01背包+完全背包)
1.hdu 2126 Buy the souvenirs 题意:给出若干个纪念品的价格,求在能购买的纪念品的数目最大的情况下的购买方案. 思路:01背包+记录方案. #include<iostr ...
随机推荐
- Linux内核中TCP SACK机制远程DoS预警通告
漏洞描述 2019年6月18日,RedHat官网发布报告:安全研究人员在Linux内核处理TCP SACK数据包模块中发现了三个漏洞,CVE编号为CVE-2019-11477.CVE-2019-114 ...
- 前端工程化与webpack
(1) 前端工程化 近几年来,前端领域飞速发展,前端的工作早已不再是切几张图,写几个页面那么简单,项目比较大时,很可能会多人协同开发,模块化,组件化,CSS预编译等技术也被广泛的使用.前端自动化( ...
- 时间戳显示格式为几天前、几分钟前、几秒前---vue过滤器
//时间显示问题(几天前.几分钟前)Vue.filter('fomatTime', function (valueTime) { if(valueTime){ var newData = Date.p ...
- JavaSE-14 异常处理
学习要点 使用try-catch-finally处理异常 使用throw.throws抛出异常 异常及其分类 log4j记录日志 异常 1 异常的定义 异常是指在程序的运行过程中所发生的不正常的事件 ...
- 四种方案解决ScrollView嵌套ListView问题 [复制链接]
以下文章转自@安卓泡面 在工作中,曾多次碰到ScrollView嵌套ListView的问题,网上的解决方法有很多种,但是杂而不全.我试过很多种方法,它们各有利弊. 在这里我将会从使用ScrollVie ...
- JS中的同步异步问题
<script> /* * JS 是单线程 * 同步 异步 * 常见的异步 * 1.定时器 * 2.事件绑定 * 3.ajax请求(一般的都是异步) * 4.回调函数也可以理解成 异步 * ...
- php 日常问题
1.isset.empty.is_null的区别 isset 判断变量是否定义或者是否为空 变量存在返回ture,否则返回false 变量定义不赋值返回false unset一个变量,返回false ...
- 开发基本的php框架
github路径:https://github.com/zhengchuzhou/easyPhpFramework 一.目录结构及用途 二.相关代码: 1.入口文件(index.php): <? ...
- Linux CentOS7.5静默安装Oracle11gR2
网上有很多安装教程,但大多不够完整,参照了一些教程,实测安装成功,整理出来分享给大家! 一.官方最低要求配置 内存:1G(官方最低要求1G) 硬盘:40G(企业版安装所需4.29G和1.7G数据文件) ...
- LNMP中PHP服务的配置
PHP(Hypertxt Preprocessor,超文本预处理器)是一种通用的开源脚本语言,发明于1995年,它吸取了C语言.Java语言及Perl语言的很多优点,具有开源.免费.快捷.跨平台性强. ...