【题意】:已知整个交易系统有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. SpringMVC的简单传值

    之前学习SpringMVC时感觉他的传值很神奇:简便,快捷,高效. 今天写几个简单的传值与大家分享,希望能对大家有帮助. 一. 从后往前传: (1) @Controller @RequestMappi ...

  2. 501在全志r16平台tinav3.0系统下调通pwm1的10KHZ波形

    501在全志r16平台tinav3.0系统下调通pwm1的10KHZ波形 2018/10/19 19:52 版本:V1.0 开发板:SC3817R SDK:tina v3.0 1.01原始编译全志r1 ...

  3. ESLint - 简介

    ESLint是一个QA工具,用来避免低级错误和统一代码的风格. ESLint被设计为完全可配置的,主要有两种方式来配置ESLint: 在注释中配置:使用JavaScript注释直接把配置嵌入到JS文件 ...

  4. 短视频SDK超级简单易用

    超级简单易用的短视频SDK来自RDSDK.COM.锐动天地为开发者提供短视频编辑.视频直播.特效.录屏.编解码.视频转换,等多种解决方案,涵盖PC.iOS.Android多平台.以市场为导向,不断打磨 ...

  5. 锐动SDK应用于行车记录仪

    方案架构 手机端直播与录播功能忠实记录旅途中各种突发事件,还原事实真相,与家人和朋友分享沿途美景,一同感受美妙之旅. 强大的视频编辑功能,像编辑图片一样给视频添加各种滤镜,配音,配乐,标题文字等特效. ...

  6. jQuery核心语法

    .each只是处理jQuery对象的方法,jQuery还提供了一个通用的jQuery.each方法,用来处理对象和数组的遍历 jQuery/($).each(array, callback )jQue ...

  7. Sublime Text 2/3 输入法修复[Ubuntu(Debian)]

    一直想找一个可以替代sublime的IDE主要还是hi因为没有好的方法解决中文输入的问题, 今天在网上找到一个非常不错的方法,亲自实验是可行的,就记录下来了,我的系统是ubuntu16.04 Subl ...

  8. ORA-39126: Worker unexpected fatal error in KUPW$WORKER.PUT_DDLS

    末尾加上EXCLUDE=STATISTICS /home/opt/oracle/11g/bin/expdp user/password directory=backup2 network_link=d ...

  9. QT5:先导篇 算法

    一.简介 QT的<QtAlgorithms>和<QtGlobal>模块提供了几种常用算法 二.QtAlgorithms 三.QtGlobal

  10. windows mac配置host方法

    配置host方法如下: 1.windows 系统配置host (1)打开电脑的系统盘(一般默认为C盘):C盘 -> Windows -> System32 -> drives -&g ...