zoukankan      html  css  js  c++  java
  • 背包(纯模板)

    回忆一下动规中的背包。。。

    一. 最基本的 01背包:

    描述:

      一个旅行者有一个最多能装 m 公斤的背包,现有 n 件物品 ,它们的重量分别为 W1、W2……Wn ,它们的价值分别为 C1、C2……Cn ,求旅行者能获得的最大总价值。

    输入:

      第一行:两个整数,m(背包容量)和 n(物品数量);

      第二行至 n+1 行:每行两个整数 Wi、Ci,表示每个物品的重量和价值。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #include<deque>
    #include<stack>
    #include<map>
    #include<set>
    using namespace std;
    #define maxm 2001
    #define maxn 301
    int m,n;
    int w[maxn],c[maxn];
    int f[maxn][maxm];
    inline int read()
    {
        int kr=1,xs=0;
        char ls;
        ls=getchar();
        while(!isdigit(ls))
        {
            if(ls=='-')
            kr=-1;
            ls=getchar();
        }
        while(isdigit(ls))
        {
            xs=(xs<<1)+(xs<<3)+(ls^48);
            ls=getchar();
        }
        return kr*xs;
    }
    int main()
    {
        m=read();n=read();
        for(int i=1;i<=n;i++)
            w[i]=read(),c[i]=read();
        for(int i=1;i<=n;i++)
            for(int v=m;v>0;v--)//逆序
                if(w[i]<=v)
                    f[i][v]=max(f[i-1][v],f[i-1][v-w[i]]+c[i]);
                else f[i][v]=f[i-1][v];
        printf("%d
    ",f[n][m]);
    return 0;
    }

    二. 完全背包

    描述:

      设有 n 种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重为 m ,今从 n 种物品中选取若干件(同一种物品可以多次选取)使其重量的和 ≤ m ,而价值的和为最大。

    输入:

      第一行:两个整数,m(背包容量)和 n (物品数量);

      第二行至 n+1 行:每行两个整数 Wi、Ci,表示每个物品的重量和价值。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #include<deque>
    #include<stack>
    #include<map>
    #include<set>
    using namespace std;
    #define maxm 2001
    #define maxn 301
    int m,n;
    int w[maxn],c[maxn];
    int f[maxn][maxm];
    inline int read()
    {
        int kr=1,xs=0;
        char ls;
        ls=getchar();
        while(!isdigit(ls))
        {
            if(ls=='-')
            kr=-1;
            ls=getchar();
        }
        while(isdigit(ls))
        {
            xs=(xs<<1)+(xs<<3)+(ls^48);
            ls=getchar();
        }
        return kr*xs;
    }
    int main()
    {
        m=read();n=read();
        for(int i=1;i<=n;i++)
            w[i]=read(),c[i]=read();
        for(int i=1;i<=n;i++)
            for(int v=1;v<=m;v++)//正序(与01背包的唯一不同) 
                if(w[i]<=v)
                    f[i][v]=max(f[i-1][v],f[i-1][v-w[i]]+c[i]);
                else f[i][v]=f[i-1][v];
        printf("%d
    ",f[n][m]);
    return 0;
    }

    三. 多重背包

    描述:

      有 n 种物品和一个容量为 m 的背包。每种物品都有各自的价值 Wi 、重量 Vi 、和能够购买数量 Si

    输入:

      第一行:两个整数,n (物品种数)和 m(背包容量);

      第二行至 n+1 行:每行三个整数 Vi、Wi、Si 表示每种物品的重量、价值和能够购买的最大数量。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #include<deque>
    #include<stack>
    #include<map>
    #include<set>
    using namespace std;
    #define maxn 6002
    int v[maxn],w[maxn],s[maxn];
    int f[maxn];
    int n,m;
    inline int read()
    {
        int kr=1,xs=0;
        char ls;
        ls=getchar();
        while(!isdigit(ls))
        {
            if(ls=='-')
            kr=-1;
            ls=getchar();
        }
        while(isdigit(ls))
        {
            xs=(xs<<1)+(xs<<3)+(ls^48);
            ls=getchar();
        }
        return kr*xs;
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)
            v[i]=read(),w[i]=read(),s[i]=read();
        for(int i=1;i<=n;i++)
            for(int j=m;j>=0;j--)//以上两重循环为 01背包 
                for(int k=0;k<=s[i];k++)
                {
                    if(j-k*v[i]<0) break;//放不下(判) 
                    f[j]=max(f[j],f[j-k*v[i]]+k*w[i]);
                }
        printf("%d
    ",f[m]);
    return 0;
    }

    四. 混合背包(01+完全+多重)

    描述:

      一个旅行者有一个最多能装 m 公斤的背包,现有 n 件物品,它们的重量分别为 W1、W2……Wn ,它们的价值分别为 C1、C2……Cn 。有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。求解将那些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

    输入:

      第一行:两个整数, m (背包容量)和 n (物品数量);

      第二行至 n+1 行:每行三个整数 Wi、Ci、Pi ,前两个整数分别表示每个物品的重量、价值,第三个整数若为 0 ,则说明此物品可以购买无数件;若为其它数字,则为此物品可够买的最多件数(Pi)。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #include<deque>
    #include<stack>
    #include<map>
    #include<set>
    using namespace std;
    #define maxn 6002
    int w[maxn],c[maxn],p[maxn];
    int f[maxn];
    int n,m;
    inline int read()
    {
        int kr=1,xs=0;
        char ls;
        ls=getchar();
        while(!isdigit(ls))
        {
            if(ls=='-')
            kr=-1;
            ls=getchar();
        }
        while(isdigit(ls))
        {
            xs=(xs<<1)+(xs<<3)+(ls^48);
            ls=getchar();
        }
        return kr*xs;
    }
    int main()
    {
        m=read();n=read();
        for(int i=1;i<=n;i++)
            w[i]=read(),c[i]=read(),p[i]=read();
        for(int i=1;i<=n;i++)
            if(p[i]==0)//完全背包 
            {
                for(int j=w[i];j<=m;j++)
                    f[j]=max(f[j],f[j-w[i]]+c[i]);
            }
            else//01背包和多重背包 
            {
                for(int j=1;j<=p[i];j++)
                    for(int k=m;k>=w[i];k--)
                    f[k]=max(f[k],f[k-w[i]]+c[i]);
            }
        printf("%d
    ",f[m]);
    return 0;
    }

    五. 二维费用背包

    描述:

      有一个背包,容纳的重量为 m 、体积为 v 。有 n 件物品,其质量为 Wi、体积为 Vi、价值为 Ci 。求,在不超过背包容纳的最大重量和体积的情况下,所能够获得的最大价值。

    输入:

      第一行:三个整数, v(背包容纳的体积)、m(背包容纳的质量)、n(物品数量);

      第二行至 n+1 行:每行三个整数 Vi 、Wi、C,分别表示物品的体积、重量和价值。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #include<deque>
    #include<stack>
    #include<map>
    #include<set>
    using namespace std;
    #define maxn 1001 
    int m[maxn],v[maxn],c[maxn];
    int f[maxn][maxn];
    int N,V,M;
    inline int read()
    {
        int kr=1,xs=0;
        char ls;
        ls=getchar();
        while(!isdigit(ls))
        {
            if(ls=='-')
            kr=-1;
            ls=getchar();
        }
        while(isdigit(ls))
        {
            xs=(xs<<1)+(xs<<3)+(ls^48);
            ls=getchar();
        }
        return kr*xs;
    }
    int main()
    {
        V=read();M=read();N=read(); 
        for(int i=1;i<=N;i++)
            v[i]=read(),m[i]=read(),c[i]=read();
        for(int i=1;i<=N;i++)
            for(int j=V;j>=v[i];j--)
                for(int k=M;k>=m[i];k--)//比01背包多一维条件 
                    f[j][k]=max(f[j][k],f[j-v[i]][k-m[i]]+c[i]);
        printf("%d
    ",f[V][M]);
        return 0;
    }

    六. 分组背包

    描述:

      一个旅行者有一个最多能装 m 公斤的背包,现在有 n 件物品,它们的重量分别为 W1、W2……Wn ,它们的价值分别为 C1、C2……Cn 。这些物品被分为若干组,每组中的物品互相冲突,最多选一件。求解将那些物品装入背包可使这些物品的费用总和不超过背包容量,且价值最大。

    输入:

      第一行:三个整数,m (背包容量)、n (物品数量)和 T (最大组号);

      第二行至 n+1 行:每行三个整数 W、C、P,表示每个物品的重量、数量和所属组号。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #include<deque>
    #include<stack>
    #include<map>
    #include<set>
    using namespace std;
    #define maxn 1001
    int n,m,t;
    int w[maxn],c[maxn];
    int a[maxn][maxn];
    int f[maxn]; 
    inline int read()
    {
        int kr=1,xs=0;
        char ls;
        ls=getchar();
        while(!isdigit(ls))
        {
            if(ls=='-')
            kr=-1;
            ls=getchar();
        }
        while(isdigit(ls))
        {
            xs=(xs<<1)+(xs<<3)+(ls^48);
            ls=getchar();
        }
        return kr*xs;
    }
    int main()
    {
        m=read();n=read();t=read();
        for(int i=1;i<=n;i++)
        {
            int p;
            w[i]=read();c[i]=read();p=read();
            a[p][++a[p][0]]=i;//(++a[p][0]为每组的数量) 
        }
        for(int k=1;k<=t;k++)
            for(int j=m;j>=0;j--)
                for(int i=1;i<=a[k][0];i++)
                    if(j>=w[a[k][i]])
                    {
                        int tmp=a[k][i];//记录该物品所属的组号 
                        f[j]=max(f[j],f[j-w[tmp]]+c[tmp]);
                    }
        printf("%d
    ",f[m]);
    return 0;
    }
  • 相关阅读:
    当在服务器或者云端发布程序的时候,注意事项
    Oracle 在使用pivot时,注意事项
    当采用datagrid自带的方法加载列表时,当在后台遇到错误时,如何在前台提示错误
    Oracle 在分组的同时,取每个分组的前几条PARTITION BY
    带有res资源文件的项目 需要导成jar包 供别人使用的解决方法
    java乱码问题
    网络通信框架Volley使用详细说明
    深刻的理解Fragment生命周期 都在做什么,fragment生命周期
    ScrollView中嵌套ListView时,listview高度显示的问题
    关于一个app中数据库的问题
  • 原文地址:https://www.cnblogs.com/lck-lck/p/9703174.html
Copyright © 2011-2022 走看看