SOJ 2749_The Fewest Coins
【题意】:已知整个交易系统有N
(1 ≤ N ≤ 100)种不同的货币,分别价值V1,V2,V3.......VN(1 ≤ Vi ≤ 120),FJ分别有C1,C2,C3.....CN(0
≤ Ci ≤10,000)张相应价值货币。FJ只能用仅有的货币去买价值T(1 ≤T≤10,000)分的东西,而老板有无数的货币可以找给他。求FJ给老板的货币数+老板找给FJ的货币数的最小值。
Input
* Line 1: Two space-separated integers: N and T.
* Line 2: N space-separated integers, respectively V1, V2, ..., VN coins (V1...VN).
* Line 3: N space-separated integers, respectively C1, C2, ..., CN
Output
* Line 1: A line containing a single integer, the minimum number of coins involved in a payment and
change-making. If it is impossible for Farmer John to pay and receive exact change, output -1.Sample Input
3 70
5 25 50
5 2 1
Sample Output
3
【分析】:将问题拆分为两部分:(多重背包+完全背包)FJ支付的货币数实是多重背包问题,而老板找给FJ的货币数可以转化为完全背包问题。
思路一:FJ最多可以给老板(N+他所拥有的货币最大面值),用t[i]保存在此区间FJ支付给老板的钱数为i时所需的最小货币数。对于[N,N+Max]区间,用l[j]表示老板找给FJ的钱数为j时的最小货币数(其中i-j=N),最终求出所有t[i]+l[j]的最小值,即为题目所求。
<span style="font-size:14px;">#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int v[110],c[110],t[24400],l[24400];
int T=0,N=0;
int Max;
const int inf =10000000;
void ZeroOnePack(int vi,int k)
{
for(int i=N+Max;i>=vi;i--)
t[i]=min(t[i],t[i-vi]+k);
}
void CompletePack(int vi,int* t,int n)
{
for(int i=vi;i<=n;i++)
t[i]=min(t[i],t[i-vi]+1);
}
void MultiplePack(int vi,int ci)
{
if(vi*ci>N+Max)
CompletePack(vi,t,N+Max);
int k=1;
while(k<ci)
{
ZeroOnePack(k*vi,k);
ci=ci-k;
k=2*k;
}
ZeroOnePack(ci*vi,ci);
}
int main (void)
{
while(~scanf("%d%d",&T,&N))
{
int Min=inf;
Max=0;
for(int i=1;i<24400i++) t[i]=inf;
t[0]=0;
for(int i=0;i<T;i++)
{
scanf("%d",&v[i]);
if(Max<v[i]) Max=v[i];
}
Max=Max*Max;//保证背包足够大
for(int i=0;i<T;i++) scanf("%d",&c[i]);
for(int i=0;i<T;i++) MultiplePack(v[i],c[i]);
for(int i=N;i<=N+Max;i++)
{
if(t[i]!=inf)
{
for(int i=0;i<24400;i++) l[i]=inf;
l[0]=0;
for(int j=0;j<T;j++)
CompletePack(v[j],l,i-N);
Min=min(Min,t[i]+l[i-N]);
}
}
if( Min==inf) Min=-1;
printf("%d\n",Min);
}
} </span>
【Spotted】
1.最初不知道应该开多大的数组保存货币数,在别人的博客中找到以下内容:
最重要的是上界的处理。可以注意到,上界为maxw*maxw+m(maxw最大面额的纸币),也就是24400元。(网上的证明)证明如下:
如果买家的付款数大于了maxw*maxw+m,即付硬币的数目大于了maxw,根据鸽笼原理,至少有两个的和对maxw取模的值相等,也就是说,这部分硬币能够用更少的maxw来代替。证毕。
【【离散不是白学的呀呵呵!
2.memset和fill相关。。。。在下一篇博客中。。。。
思路二:使用同一个数组【想了好久都感觉无解,看了别人的代码才顿悟。。。。窒息。。。。】
改一下main函数,代码如下:
<span style="font-family:Microsoft YaHei;font-size:14px;">int main (void)
{
while(~scanf("%d%d",&T,&N))
{
int Min=inf;
Max=0;
for(int i=1;i<24400;i++) t[i]=inf;
t[0]=0;
for(int i=0;i<T;i++)
{
scanf("%d",&v[i]);
if(Max<v[i]) Max=v[i];
}
Max=Max*Max;//保证背包足够大 for(int i=0;i<T;i++) scanf("%d",&c[i]);
for(int i=0;i<T;i++) MultiplePack(v[i],c[i]);
for(int i=0;i<T;i++)
{
for(int k= N+Max-v[i]; k>=N; k--)
t[k]=min(t[k],t[k+v[i]]+1);
//由于是老板还给FJ的钱,且是完全背包问题,所以正负号相反,且逆序进行循环
}
if( t[N]==inf) t[N]=-1;;
printf("%d\n",t[N]);
}
}</span>
SOJ 2749_The Fewest Coins的更多相关文章
- POJ3260The Fewest Coins[背包]
The Fewest Coins Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6299 Accepted: 1922 ...
- POJ3260——The Fewest Coins(多重背包+完全背包)
The Fewest Coins DescriptionFarmer John has gone to town to buy some farm supplies. Being a very eff ...
- The Fewest Coins POJ - 3260
The Fewest Coins POJ - 3260 完全背包+多重背包.基本思路是先通过背包分开求出"付出"指定数量钱和"找"指定数量钱时用的硬币数量最小值 ...
- POJ 3260 The Fewest Coins(多重背包+全然背包)
POJ 3260 The Fewest Coins(多重背包+全然背包) http://poj.org/problem?id=3260 题意: John要去买价值为m的商品. 如今的货币系统有n种货币 ...
- POJ 3260 The Fewest Coins(完全背包+多重背包=混合背包)
题目代号:POJ 3260 题目链接:http://poj.org/problem?id=3260 The Fewest Coins Time Limit: 2000MS Memory Limit: ...
- (混合背包 多重背包+完全背包)The Fewest Coins (poj 3260)
http://poj.org/problem?id=3260 Description Farmer John has gone to town to buy some farm supplies. ...
- POJ3260:The Fewest Coins(混合背包)
Description Farmer John has gone to town to buy some farm supplies. Being a very efficient man, he a ...
- POJ 3260 The Fewest Coins(多重背包问题, 找零问题, 二次DP)
Q: 既是多重背包, 还是找零问题, 怎么处理? A: 题意理解有误, 店主支付的硬币没有限制, 不占额度, 所以此题不比 1252 难多少 Description Farmer John has g ...
- 洛谷P2851 [USACO06DEC]最少的硬币The Fewest Coins(完全背包+多重背包)
题目描述 Farmer John has gone to town to buy some farm supplies. Being a very efficient man, he always p ...
随机推荐
- [BZOJ1798][AHOI2009]Seq维护序列 线段树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1798 一眼看过去线段树,事实上就是线段树.对于乘和加的两个标记,我们可以规定一个顺序,比如 ...
- 微信轻松接入QQ客服
一直以来,大家都苦恼怎么实现微信公众帐号可以接入客服,也因此很多第三方接口平台也开发客服系统CRM系统,不过不是操作复杂就是成本太高.今天分享一个低成本又简便的方法,让你的公众帐号接入QQ客服.下面介 ...
- 从0开始搭建SQL Server 2012 AlwaysOn 第一篇(AD域与DNS)
随着业务发展,公司需要提高数据安全与性能需求,所以需要对新技术预研(先采坑),做技术积累: 了解相关AlwaysOn 故障转移集群(热备),数据路由(ICX),Moebius(莫比斯数据路由) 决定测 ...
- android 开源
http://blog.csdn.net/xiaoxiao_job/article/details/45196119?ref=myread MPAndroidChart https://github. ...
- AIX 10G HA RAC卸载
删除 1:crs_stat –t资源都停掉 2:停ha 3: 删除oracle 4:删除crs 5: 删除ha smit hacmp 6: 删除vg exportvg 7;卸载hacmp smitty
- chpasswd - 成批更新用户的口令
总览 chpasswd [-e] 描述 chpasswd 从系统的标准输入读入用户的名称和口令,并利用这些信息来更新系统上已存在的用户的口令.在没有用 -e 这个开关选项的情况下,口令将按明文的形式接 ...
- Java SE、Java EE、Java ME 三者区别
现在一个个来分析 1. Java SE(Java Platform,Standard Edition).Java SE 以前称为 J2SE.它允许开发和部署在桌面.服务器.嵌入式环境和实时环境中使用的 ...
- 不能局部安装webpack的解决方法
npm ERR! code ENOSELFnpm ERR! Refusing to install package with name "webpack" under a pack ...
- vue 常用功能和命令
1. vue-cli 构建项目 # 全局安装 vue-cli $ npm install --global vue-clif # 创建一个基于 webpack 模板的新项目 $ vue init we ...
- Linux C下变量和常量的存储的本质
源代码 #cat main.c #include <stdio.h> int i = 100; int main(void) { func(); return 0; } #cat func ...