简单背包问题

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

 

 

 

posted @ 2020-01-22 11:41  朝暮不思  阅读(322)  评论(0编辑  收藏  举报