• 背包问题--(一本通)课后训练


    1.打包

    /*一个二维01背包
    样例输入: 
    6 5 4
    10 2 2
    20 3 2
    40 4 3
    30 3 3
    样例输出:
    50 
    */
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #define N 381
    int f[N][N];
    int n,V,G;
    struct Wp{
        int t,v,g;
    };
    Wp wp[N];
    void input()
    {
        scanf("%d%d%d",&V,&G,&n);
        for(int i=1;i<=n;++i)
        scanf("%d%d%d",&wp[i].t,&wp[i].v,&wp[i].g);
    }
    void dp()
    {
        for(int i=1;i<=n;++i)
          for(int j=V;j>=wp[i].v;--j)
            for(int k=G;k>=wp[i].g;--k)
            f[j][k]=max(f[j][k],f[j-wp[i].v][k-wp[i].g]+wp[i].t);
        cout<<f[V][G]<<endl;
    }
    int main()
    {
        input();
        dp();
        return 0;
    }
    View Code

    2.砝码称重

    #include<iostream>
    using namespace std;
    #include<cstdio>
    int a[7];
    bool num[1001]={false};
    int main()
    {
        for(int i=1;i<=6;++i)
        scanf("%d",&a[i]);
        for(int q=0;q<=a[1];++q)
          for(int w=0;w<=a[2];++w)  
            for(int e=0;e<=a[3];++e)
              for(int r=0;r<=a[4];++r)
                for(int t=0;t<=a[5];++t)
                  for(int y=0;y<=a[6];++y)
                  {
                      int ll=q*1+w*2+e*3+r*5+t*10+y*20;
                      num[ll]=true;
                  }
        int sum=0;
        for(int i=1;i<=1000;++i)
        if(num[i]) sum++;
        cout<<"Total="<<sum<<endl;
        return 0;
     } 
    View Code

    3.竞赛总分

    /*一个简单的完全背包*/
    #include<iostream>
    using namespace std;
    #include<cstdio>
    struct Que{
        int tim,fs;
    };
    int dp[10001];
    Que que[10001];
    int n,m;
    void input()
    {
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;++i)
        scanf("%d%d",&que[i].fs,&que[i].tim);
    }
    
    int DP()
    {
        for(int i=1;i<=n;++i)
          for(int j=que[i].tim;j<=m;++j)
          dp[j]=max(dp[j],dp[j-que[i].tim]+que[i].fs);
    }
    int main()
    {
        freopen("inflate.in","r",stdin);
        freopen("inflate.out","w",stdout);
        input();
        DP();
        printf("%d
    ",dp[m]);
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    View Code

     4.最小乘车费用

     时间限制: 1 s
     空间限制: 256000 KB
     题目等级 : 黄金 Gold
    题目描述 Description

    假设某条街上每一公里就有一个公共汽车站,并且乘车费用如下:

    公里数   1    2    3    4    5     6    7     8     9    10

    费用      12  21  31  40  49  58  69   79   90   101

    任意一辆汽车从不行驶超过10公里。某人想行驶n公里,可以任意次换车,请帮他找到一种乘车方案,使得费用最小。

    注意:10公里的费用是可以比1公里小的。

    输入描述 Input Description

    输入文件共两行,

    第一行为10个不超过200的整数,依次表示1~10公里的费用。

    第二行为某人想要行驶的公里数。

    输出描述 Output Description

    输出仅一行,为乘车的最小费用。

    样例输入 Sample Input

    12 21 31 40 49 58 69 79 90 101

    15

    样例输出 Sample Output

    147

    /*一个恰好装满的完全背包,因为是求最小值,就把f[i]=大数,f[0]=0这样只有刚好走到,才更新*/
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #define N 100001
    struct Lc{
        int len,fare;
    };
    Lc lc[11];
    int f[N],n;
    #include<cstring>
    void input()
    {
        for(int i=1;i<=10;++i)
        {
            scanf("%d",&lc[i].fare);
            lc[i].len=i;
        }
        scanf("%d",&n);
    }
    void dp()
    {
        memset(f,99,sizeof(f));
        f[0]=0;
        for(int i=1;i<=10;++i)
          for(int j=lc[i].len;j<=n;++j)
          f[j]=min(f[j],f[j-lc[i].len]+lc[i].fare);
        cout<<f[n]<<endl;
    }
    int main()
    {
        input();
        dp();
        return 0;
    }
    View Code

    5.逃亡的准备

    /*多重背包的二进制拆分*/
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #define N 2001
    #define V 501
    int n,vv;
    struct Wp{
        int v,val;
    }; 
    Wp wp[N];
    int f[V],t=0;
    void input()
    {
        scanf("%d%d",&n,&vv);
        int cou,v1,val1;
        for(int i=1;i<=n;++i)
        {
            scanf("%d%d%d",&cou,&v1,&val1);
            if(cou==1)
            {
                ++t;
                wp[t].v=v1;
                wp[t].val=val1;
                
                continue;
            }
            for(int j=1;j<=cou;j<<=1)
            {
                ++t;
                wp[t].v=j*v1;
                wp[t].val=j*val1;
                cou-=j;
            }
            if(cou>0)
            {
                ++t;
                wp[t].v=cou*v1;
                wp[t].val=cou*val1;
            }
        }
    }
    void DP()
    {
        for(int i=1;i<=t;++i) 
          for(int j=vv;j>=wp[i].v;--j)
           f[j]=max(f[j],f[j-wp[i].v]+wp[i].val);
        cout<<f[vv]<<endl;
    }
    int main()
    {
        freopen("hallows.in","r",stdin);
        freopen("hallows.out","w",stdout);
        input();
        DP();
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    View Code

    6.暗黑游戏

    /*多重背包的三循环做法*/
    #include<iostream>
    using namespace std;
    #include<cstdio>
    int n,P,R;
    struct Wp{
        int p,r,count,zd;
    };
    Wp wp[151];
    int dp[101][101];
    void input()
    {
        scanf("%d%d%d",&n,&P,&R);
        for(int i=1;i<=n;++i)
        {
            cin>>wp[i].p>>wp[i].r>>wp[i].count>>wp[i].zd;
            
        }
        
    }
    void DP()
    {
        for(int i=1;i<=n;++i)
        {
            if(wp[i].count==0)
            {
                for(int j=wp[i].r;j<=R;++j)
                  for(int k=wp[i].p;k<=P;++k)
                    for(int s=0;s<=wp[i].count;++s)
                    if(j-s*wp[i].r>=0&&k-s*wp[i].p>=0)
                  dp[j][k]=max(dp[j][k],dp[j-s*wp[i].r][k-s*wp[i].p]+s*wp[i].zd);
                     else break;
            }
            else 
            {
                for(int j=R;j>=wp[i].r;--j)
                  for(int k=P;k>=wp[i].p;--k)
                   for(int s=0;s<=wp[i].count;++s)
                   if(j-s*wp[i].r>=0&&k-s*wp[i].p>=0)
                  dp[j][k]=max(dp[j][k],dp[j-s*wp[i].r][k-s*wp[i].p]+s*wp[i].zd);
                    else break;
            }
        }
    }
    int main()
    {
        freopen("pgrune.in","r",stdin);
        freopen("pgrune.out","w",stdout);
        //ios::sync_with_stdio(false);/*加上这句结构体就没有了值*/
        input();
        DP();
        cout<<dp[R][P]<<endl;
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    View Code

    7.潜水员(必须拿够的背包问题)

    【例5】潜水员
    问题描述
    w    潜水员为了潜水要使用特殊的装备。他有一个带2种气体的气缸:一个为氧气,一个为氮气。让潜水员下潜的深度需要各种的数量的氧和氮。潜水员有一定数量的气缸。每个气缸都有重量和气体容量。潜水员为了完成他的工作需要特定数量的氧和氮。他完成工作所需气缸的总重的最低限度的是多少?
    w    例如:潜水员有5个气缸。每行三个数字为:氧,氮的(升)量和气缸的重量:
    w    3 36 120
    w    10 25 129
    w    5 50 250
    w    1 45 130
    w    4 20 119
    w    如果潜水员需要5升的氧和60升的氮则总重最小为249(1,2或者4,5号气缸)。
    w    你的任务就是计算潜水员为了完成他的工作需要的气缸的重量的最低值。
    【输入格式】
    w  第一行有2整数m,n(1<=m<=21,1<=n<=79)。它们表示氧,氮各自需要的量。
    w  第二行为整数k(1<=n<=1000)表示气缸的个数。
    w  此后的k行,每行包括ai,bi,ci(1<=ai<=21,1<=bi<=79,1<=ci<=800)3整数。这些各自是:第i个气缸里的氧和氮的容量及汽缸重量。
    【输出格式】
    w  仅一行包含一个整数,为潜水员完成工作所需的气缸的重量总和的最低值。
     
    /*必须拿够的背包问题:*/
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #include<cstring>
    int m,n,k;
    int f[300][300];
    struct G{
        int a,b,c;
    };
    G g[101];
    int main()
    {
        freopen("swim.in","r",stdin);
        freopen("swim.out","w",stdout);
        ios::sync_with_stdio(false);
        cin>>m>>n>>k;
        memset(f,99,sizeof(f));
        for(int i=1;i<=k;++i)
        cin>>g[i].a>>g[i].b>>g[i].c;
        f[0][0]=0;/*只把f[0][0]赋值为0,为了把背包恰好装满*/
        for(int i=1;i<=k;++i)
          for(int j=2*m;j>=g[i].a;--j)
            for(int l=2*n;l>=g[i].b;--l)
            f[j][l]=min(f[j][l],f[j-g[i].a][l-g[i].b]+g[i].c);
        int sum=999999;
        for(int i=m;i<=2*m;++i)/*因为氧气和氮气可以拿多了,所以从m到2吗,n到2n上寻找最小值*/
          for(int j=n;j<=2*n;++j)
          if(f[i][j]<sum)
          {
              sum=f[i][j];
          }
        cout<<sum<<endl;
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    View Code

    8.庆功会

    【问题描述】
    w为了庆贺班级在校运动会上取得全校第一名成绩,班主任决定开一场庆功会,为此拨款购买奖品犒劳运动员。期望拨款金额能购买最大价值的奖品,可以补充他们的精力和体力。
    【输入格式】
    w第一行二个数n(n<=500),m(m<=6000),其中n代表希望购买的奖品的种数,m表示拨款金额。
    w接下来n行,每行3个数,v、w、s,分别表示第I种奖品的价格、价值(价格与价值是不同的概念)和购买的数量(0件到s件均可),其中v<=100,w<=1000,s<=10。
    【输出格式】
    w第一行:一个数,表示此次购买能获得的最大的价值(注意!不是价格)。
    【输入样例】
    w5 1000
    w80 20 4
    w40 50 9
    w30 50 7
    w40 30 6
    w20 20 1
    【输出样例】
    w1040
    代码:
    /*一个多重背包*/
    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m,f[6001];
    struct Wp{
        int v,w,s;
    }; 
    Wp wp[501];
    int main()
    {
        freopen("庆功会.in","r",stdin);
        freopen("庆功会.out","w",stdout);
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1;i<=n;++i)
        cin>>wp[i].v>>wp[i].w>>wp[i].s;
        for(int i=1;i<=n;++i)
          for(int j=m;j>0;--j)
            for(int k=0;k<=wp[i].s;++k)
            if(j>k*wp[i].v)
            f[j]=max(f[j],f[j-k*wp[i].v]+k*wp[i].w);
            else break;
        cout<<f[m]<<endl;
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    View Code

     9.暗黑破坏神

  • 相关阅读:
    FAST for SharePoint如何重置Index
    SharePoint 2007有性能问题? 先试试这篇.
    "Cannot generate SSPI context"
    记录一个用过的SQL脚本(select * into)
    IISRESET为什么有时候要带个noforce参数?
    SharePoint跟权限有关的Object Model Class
    DotNET也谈组合强命名破解FlyGrid 1.5.0.31963 for VS2003
    应同学之邀,破解一个软件,学习逆向工程,文章如下
    win2003下建立*.*到asp.net的映射(安装CNBlogsDotText用)
    MS.Net CLR 扩展PE结构分析
  • 原文地址:https://www.cnblogs.com/c1299401227/p/5325213.html
Copyright © 2020-2023  润新知