• 一本通1601【例 5】Banknotes


    1601:【例 5】Banknotes

    时间限制: 1000 ms         内存限制: 524288 KB

    【题目描述】

    原题来自:POI 2005

    Byteotian Bit Bank (BBB) 拥有一套先进的货币系统,这个系统一共有 n 种面值的硬币,面值分别为 b1,b2,,bn。但是每种硬币有数量限制,现在我们想要凑出面值 k,求最少要用多少个硬币。

    【输入】

    第一行一个数 n;

    接下来一行 n 个整数 b1,b2,,bn

    第三行 n 个整数 c1,c2,,cn ,表示每种硬币的个数;

    最后一行一个数 k,表示要凑的面值数。

    【输出】

    第一行一个数表示最少需要付的硬币数。

    【输入样例】

    3
    2 3 5
    2 2 1
    10

    【输出样例】

    3

    【提示】

    数据范围与提示:

    对于全部数据,1n200,1b1<b2<<bn2×104,1ci,k2×104 。

    sol:比较裸的完全背包??可以有两种优化:

    二进制优化太水不说了

    #include <bits/stdc++.h>
    using namespace std;
    typedef int ll;
    inline ll read()
    {
        ll s=0;
        bool f=0;
        char ch=' ';
        while(!isdigit(ch))
        {
            f|=(ch=='-');
            ch=getchar();
        }
        while(isdigit(ch))
        {
            s=(s<<3)+(s<<1)+(ch^48);
            ch=getchar();
        }
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x<10)
        {
            putchar(x+'0');
            return;
        }
        write(x/10);
        putchar((x%10)+'0');
        return;
    }
    inline void writeln(ll x)
    {
        write(x);
        putchar('
    ');
        return;
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) writeln(x)
    const int N=20005,M=2000005;
    int n,m,B[N],C[N],dp[M];
    int main()
    {
        int i,j,k;
        R(n);
        for(i=1;i<=n;i++) R(B[i]);
        for(i=1;i<=n;i++) R(C[i]);
        R(m);
        memset(dp,63,sizeof dp);
        dp[0]=0;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=C[i]&&j*B[i]<=m;j<<=1)
            {
                for(k=m;k>=j*B[i];k--) dp[k]=min(dp[k],dp[k-j*B[i]]+j);
            }
        }
        Wl(dp[m]);
        return 0;
    }
    /*
    input
    3
    2 3 5
    2 2 1
    10
    output
    3
    
    input
    10
    6 17 111 249 250 495 496 497 498 499
    100 100 100 100 1 100 100 100 100 100
    500
    output
    6
    
    input
    3
    300 700 4800
    10000 10000 10000
    5000
    output
    10
    */
    二进制优化

    单调队列优化:对于模Bi相同的几个权值之间的dp转移,可以用单调队列优化,令权值V=j+k*Bi,dp[V]=min(dp[V],dp[j+k'*Bi]+k-k‘),所以可以用dp[j+k*Bi]-k最小为队首的单调队列来优化成n*m,(细节:为了防止被反复统计,应该先插入当前节点再更新当前节点的dp值)

    #include <bits/stdc++.h>
    using namespace std;
    typedef int ll;
    inline ll read()
    {
        ll s=0;
        bool f=0;
        char ch=' ';
        while(!isdigit(ch))
        {
            f|=(ch=='-');
            ch=getchar();
        }
        while(isdigit(ch))
        {
            s=(s<<3)+(s<<1)+(ch^48);
            ch=getchar();
        }
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x<10)
        {
            putchar(x+'0');
            return;
        }
        write(x/10);
        putchar((x%10)+'0');
        return;
    }
    inline void writeln(ll x)
    {
        write(x);
        putchar('
    ');
        return;
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) writeln(x)
    const int N=205,M=20005;
    int n,m,B[N],C[N],dp[M];
    struct Data
    {
        int Shuz,Weiz;
    }Ddq[M];
    int main()
    {
        int i,j,k;
        R(n);
        for(i=1;i<=n;i++) R(B[i]);
        for(i=1;i<=n;i++) R(C[i]);
        R(m);
        memset(dp,63,sizeof dp);
        dp[0]=0;
        for(i=1;i<=n;i++)
        {
            for(j=0;j<B[i];j++)
            {
                int Head=1,Tail=0;
                for(k=0;;k++)
                {
                    int x=k*B[i]+j; if(x>m) break;
                    while(Head<Tail&&Ddq[Head].Weiz<k-C[i]) Head++;
                    while(Head<=Tail&&dp[x]-k<Ddq[Head].Shuz-Ddq[Head].Weiz) Tail--;
                    Ddq[++Tail]=(Data){dp[x]-k,k};
                    dp[x]=min(dp[x],Ddq[Head].Shuz+k);
                }
            }
        }
        Wl(dp[m]);
        return 0;
    }
    /*
    input
    3
    2 3 5
    2 2 1
    10
    output
    3
    */
    单调队列优化
  • 相关阅读:
    io学习
    asp.net文件上传进度条研究
    asp.net页面中的Console.WriteLine结果如何查看
    谨慎跟随初始目的不被关联问题带偏
    android 按钮特效 波纹 Android button effects ripple
    安卓工作室 日志设置
    安卓工作室 文件浏览器 android studio File browser
    一个新的Android Studio 2.3.3可以在稳定的频道中使用。A new Android Studio 2.3.3 is available in the stable channel.
    新巴巴运动网上商城 项目 快速搭建 教程 The new babar sports online mall project quickly builds a tutorial
    码云,git使用 教程-便签
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10371987.html
Copyright © 2020-2023  润新知