【题意】:已知整个交易系统有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的更多相关文章

  1. POJ3260The Fewest Coins[背包]

    The Fewest Coins Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6299   Accepted: 1922 ...

  2. POJ3260——The Fewest Coins(多重背包+完全背包)

    The Fewest Coins DescriptionFarmer John has gone to town to buy some farm supplies. Being a very eff ...

  3. The Fewest Coins POJ - 3260

    The Fewest Coins POJ - 3260 完全背包+多重背包.基本思路是先通过背包分开求出"付出"指定数量钱和"找"指定数量钱时用的硬币数量最小值 ...

  4. POJ 3260 The Fewest Coins(多重背包+全然背包)

    POJ 3260 The Fewest Coins(多重背包+全然背包) http://poj.org/problem?id=3260 题意: John要去买价值为m的商品. 如今的货币系统有n种货币 ...

  5. POJ 3260 The Fewest Coins(完全背包+多重背包=混合背包)

    题目代号:POJ 3260 题目链接:http://poj.org/problem?id=3260 The Fewest Coins Time Limit: 2000MS Memory Limit: ...

  6. (混合背包 多重背包+完全背包)The Fewest Coins (poj 3260)

    http://poj.org/problem?id=3260   Description Farmer John has gone to town to buy some farm supplies. ...

  7. POJ3260:The Fewest Coins(混合背包)

    Description Farmer John has gone to town to buy some farm supplies. Being a very efficient man, he a ...

  8. POJ 3260 The Fewest Coins(多重背包问题, 找零问题, 二次DP)

    Q: 既是多重背包, 还是找零问题, 怎么处理? A: 题意理解有误, 店主支付的硬币没有限制, 不占额度, 所以此题不比 1252 难多少 Description Farmer John has g ...

  9. 洛谷P2851 [USACO06DEC]最少的硬币The Fewest Coins(完全背包+多重背包)

    题目描述 Farmer John has gone to town to buy some farm supplies. Being a very efficient man, he always p ...

随机推荐

  1. [BZOJ1798][AHOI2009]Seq维护序列 线段树

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1798 一眼看过去线段树,事实上就是线段树.对于乘和加的两个标记,我们可以规定一个顺序,比如 ...

  2. 微信轻松接入QQ客服

    一直以来,大家都苦恼怎么实现微信公众帐号可以接入客服,也因此很多第三方接口平台也开发客服系统CRM系统,不过不是操作复杂就是成本太高.今天分享一个低成本又简便的方法,让你的公众帐号接入QQ客服.下面介 ...

  3. 从0开始搭建SQL Server 2012 AlwaysOn 第一篇(AD域与DNS)

    随着业务发展,公司需要提高数据安全与性能需求,所以需要对新技术预研(先采坑),做技术积累: 了解相关AlwaysOn 故障转移集群(热备),数据路由(ICX),Moebius(莫比斯数据路由) 决定测 ...

  4. android 开源

    http://blog.csdn.net/xiaoxiao_job/article/details/45196119?ref=myread MPAndroidChart https://github. ...

  5. AIX 10G HA RAC卸载

    删除 1:crs_stat –t资源都停掉 2:停ha 3: 删除oracle 4:删除crs 5: 删除ha smit hacmp 6: 删除vg exportvg 7;卸载hacmp smitty

  6. chpasswd - 成批更新用户的口令

    总览 chpasswd [-e] 描述 chpasswd 从系统的标准输入读入用户的名称和口令,并利用这些信息来更新系统上已存在的用户的口令.在没有用 -e 这个开关选项的情况下,口令将按明文的形式接 ...

  7. Java SE、Java EE、Java ME 三者区别

    现在一个个来分析 1. Java SE(Java Platform,Standard Edition).Java SE 以前称为 J2SE.它允许开发和部署在桌面.服务器.嵌入式环境和实时环境中使用的 ...

  8. 不能局部安装webpack的解决方法

    npm ERR! code ENOSELFnpm ERR! Refusing to install package with name "webpack" under a pack ...

  9. vue 常用功能和命令

    1. vue-cli 构建项目 # 全局安装 vue-cli $ npm install --global vue-clif # 创建一个基于 webpack 模板的新项目 $ vue init we ...

  10. Linux C下变量和常量的存储的本质

    源代码 #cat main.c #include <stdio.h> int i = 100; int main(void) { func(); return 0; } #cat func ...