• 蓝精灵算法进阶——动态规划背包(1)


    我觉得我还是分好几篇写这个东西吧-嗷;

    PACK

    还有一个网站背包模板都有;AcW

    1.01背包

    有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。

    第 i 件物品的体积是 vi,价值是 wi

    求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
    输出最大价值。

    思路:用已经处理好的物品作为dp的阶段,每种物品仅有一件,可以选择放或不放。

    即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:

    f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]};

    但还可以进一步优化我们可以省去f数组的第一维,只用一维数组,f[j]表示外层循环到i时,已经装了总体积为j的物品的最大价值和;

    注意j到倒序循环,这样可以保证每个物品只被选择一次。

    #include<bits/stdc++.h>
    using namespace std;
    #define N 500010
    template<typename T>inline void read(T &x)
    {
        x=0;T f=1,ch=getchar();
        while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
        while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
        x*=f;
    }
    int n,v,f[N],c[N],w[N];
    int main()
    {
        read(n);read(v);
        for(int i=1;i<=n;i++)
            read(c[i]),read(w[i]);
        for(int i=1;i<=n;i++)
            for(int j=v;j>=c[i];j--)
                f[j]=max(f[j],f[j-c[i]]+w[i]);
        cout<<f[v]<<endl;
        return 0;
    }
    View Code

    当然顺带写一下另一种形式,01背包统计方案数;

    CH 5201

    n为物品,m为题解,这里我们的f[j]表示和为j的方案数,max改为求和;

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1100;
    template<typename T>inline void read(T &x)
    {
        x=0;T f=1,ch=getchar();
        while (!isdigit(ch) && ch^'-') ch=getchar();
        if (ch=='-') f=-1, ch=getchar();
        while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
        x*=f;
    }
    int a[maxn],f[maxn];
    int main()
    {
        int n,m;
        read(n);read(m);
        for (int i=1;i<=n;++i)
            read(a[i]);
        f[0]=1;
        for (int i=1;i<=n;++i)
            for (int j=m;j>=a[i];--j)
                f[j]+=f[j-a[i]];
        printf("%d
    ",f[m]);
        return 0;
    }
    View Code

    2.完全背包

    和01背包不同,这里的物品有无数件,当然可以考虑二维去实现,但是像01背包一样可以进行优化,当我们采用正序循环,对应每个物品可以选择无数次,

    #include<bits/stdc++.h>
    using namespace std;
    #define N 500010
    template<typename T>inline void read(T &x)
    {
        x=0;T f=1,ch=getchar();
        while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
        while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
        x*=f;
    }
    int n,v,f[N],c[N],w[N];
    int main()
    {
        read(n);read(v);
        for(int i=1;i<=n;i++)
            read(c[i]),read(w[i]);
        for(int i=1;i<=n;i++)
            for(int j=c[i];j<=v;j++)
                f[j]=max(f[j],f[j-c[i]]+w[i]);
        cout<<f[v]<<endl;
        return 0;
    }
    View Code

    统计方案数:

    CH 5202

    我们在完全背包的基础上将max改为求和就可以了;

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=4010;
    template<typename T>inline void read(T &x)
    {
        x=0;T f=1,ch=getchar();
        while (!isdigit(ch) && ch^'-') ch=getchar();
        if (ch=='-') f=-1, ch=getchar();
        while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
        x*=f;
    }
    int f[maxn];
    int main()
    {
        int n;read(n);
        f[0]=1;
        for (int i=1;i<=n;++i)
            for (int j=i;j<=n;++j)
                f[j]=(f[j]+f[j-i])%2147483648u;
        printf("%d
    ",f[n]>0?f[n]-1:2147483647);
        return 0;
    }
    View Code

    3.多个体积维度的01背包;

    POJ 1015

    CH POJ 1015

  • 相关阅读:
    leetcode 13. Roman to Integer
    python 判断是否为有效域名
    leetcode 169. Majority Element
    leetcode 733. Flood Fill
    最大信息系数——检测变量之间非线性相关性
    leetcode 453. Minimum Moves to Equal Array Elements
    leetcode 492. Construct the Rectangle
    leetcode 598. Range Addition II
    leetcode 349. Intersection of Two Arrays
    leetcode 171. Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/Tyouchie/p/10648214.html
Copyright © 2020-2023  润新知