• 简单背包问题


    G - 小明系列故事——买年货 HDU4501

    三维费用背包,枚举积分,钱数和免费个数

    多维费用背包要在循环体内设计比较,而不能直接在for循环语句中设置类似普通01背包的语句j>=a[i]这样的语句,因为即使有一维不能满足,不代表其他维不能满足,这样会丢弃部分情况

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<map>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=110;
    int f[N][N][N];
    int n,v1,v2,kk;
    struct node {
     int a,b;
     int w; 
    
    }s[N];
    int main(){
       while(cin>>n>>v1>>v2>>kk){
           int i;
           for(i=1;i<=n;i++)
           cin>>s[i].a>>s[i].b>>s[i].w;
        int j,l,k;
        memset(f,0,sizeof f);
           for(i=1;i<=n;i++){
               for(j=v1;j>=0;j--){
                  for(k=v2;k>=0;k--){
                      for(l=kk;l>=0;l--){
                          int tmp=0;
                          if(j-s[i].a>=0)
                          tmp=max(tmp,f[j-s[i].a][k][l]+s[i].w);
                          if(k-s[i].b>=0)
                          tmp=max(tmp,f[j][k-s[i].b][l]+s[i].w);
                          if(l-1>=0)
                          tmp=max(tmp,f[j][k][l-1]+s[i].w);
                          f[j][k][l]=max(f[j][k][l],tmp);
                    }
                  }
               }
           }
           cout<<f[v1][v2][kk]<<endl;
       }
    }
    View Code

    A - 饭卡 HDU2546

    进行转换后就是普通01背包,转换就是,先提出最大的价值,取m-5作为最大容量计算,算出来最大是多少,再用m-dp[m-5]-a[n]。

    本题的心路历程是,我们第一眼肯定是想到最大的最后买,但是我们接下来要证明这是正确的,我相信很多人会有疑惑,为什么在dp完后再买最大的是最好的。

    因为假设存在最后买的并不是最大的,设为mid,那么一定可以把mid和最大的进行交换,下面我们来举个例子

    假如最大是15,mid是10,我们在m-5用掉最多40块钱,m是50,那么这种情况的解是0,假设这是答案,那么这可以转化为我们用掉35块钱,最后再买15块,答案也是0,类推其他也是一样,因为转换不会影响总和。

    所以进行m-5的01背包即可

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5;
    const int inf=0x3f3f3f3f;
    int a[N];
    int f[N];
    int main(){
       int n;
       int i,j;
       while(cin>>n,n){
       memset(f,0,sizeof f);
       for(i=1;i<=n;i++)
       cin>>a[i];
       int m;
       cin>>m;
       if(m<5){
           cout<<m<<endl;
           continue;
       }
       sort(a+1,a+n+1);
       int sign=a[n];
       for(i=1;i<=n-1;i++){
            for(j=m-5;j>=a[i];j--){
                f[j]=max(f[j],f[j-a[i]]+a[i]);
            } 
        }
        cout<<m-f[m-5]-sign<<endl;
       }
    }
    View Code

    D - FATE    HDU - 2159

    本题是完全背包的变形,只需要设计二维状态,杀怪的时候必须要从杀怪总数-1的位置转移,其他就是完全背包,我使用了滚动数组优化

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=110+5;
    const int inf=0x3f3f3f3f;
    int a[N];
    int b[N];
    int f[N][N];
    int main(){
        int n,m,k,s;
        while(cin>>n>>m>>k>>s){
        int i;
        for(i=1;i<=k;i++)
        cin>>a[i]>>b[i];
        int res=inf;
        memset(f,0,sizeof f);
        for(i=1;i<=k;i++){
            for(int j=b[i];j<=m;j++){
                for(int x=1;x<=s;x++){
                    f[j][x]=max(f[j][x],f[j-b[i]][x-1]+a[i]);
                    if(f[j][x]>=n)
                    res=min(j,res);
                }
            }
        }
        if(res!=inf)
        cout<<m-res<<endl;
        else
        cout<<-1<<endl;
        }
        
        
    }
    View Code

     

  • 相关阅读:
    JS 心得总结
    zk 隐藏网页文件后缀
    zk label控件内容换行
    ZK 代码自动提示
    zk 获取session,request,servletContext,response
    zk回车事件
    zk jquery的使用
    zk listbox 点击列标题实现排序功能
    Django框架学习----视图与模板(最新文章实现)
    Django框架学习----视图与模板(分页功能)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12228271.html
Copyright © 2020-2023  润新知