背包专题

来源:互联网 发布:企业网站域名备案流程 编辑:程序博客网 时间:2024/05/22 11:33



     AC Hdu 2602 Bone Collector 非常常规的01背包问题,用一维和二维数组都可以做,一维快相当多。

#include<stdlib.h>#include<ctype.h>#include<algorithm>#include<vector>#include<string>#include<queue>#include<stack>#include<set>#include<map>#include <string>#include <sstream>using namespace std;int max(int a,int b){    if(a>b)        return a;    else        return b;}int main(){    int t;    scanf("%d",&t);    int a[1000],c[1000],dp[10000];    while(t--)    {        int n,v;        scanf("%d%d",&n,&v);        for(int i=0;i<n;i++)            scanf("%d",&a[i]);        for(int i=0;i<n;i++)            scanf("%d",&c[i]);            memset(dp,0,sizeof(dp));            for(int i=0;i<n;i++)            for(int j=v;j>=0;j--)            {                if(j-c[i]>=0)                    dp[j]=max(dp[j],dp[j-c[i]]+a[i]);            }            printf("%d\n",dp[v]);    }}



     AC Poj 3624 Charm Bracelet  赤裸裸的01背包问题。

#include "iostream"#include "math.h"using namespace std;int max(int a,int b){    if(a>b)        return a;    else        return b;}int main(){    int n,m;    int a[40000],b[40000];    int dp[40000];    while( cin>>n>>m )    {        for(int i=0;i<n;i++)            cin>>a[i]>>b[i];memset(dp,0,sizeof(dp));            for(int i=0;i<n;i++)                for(int j=m;j>=0;j--)            {                if(j-a[i]>=0)                    dp[j]=max(dp[j],dp[j-a[i]]+b[i]);            }            cout<<dp[m]<<endl;    }}



     AC Hdu 2546 饭卡 n种菜选若干种使剩下的钱最少,背包容量是开始时的钱,物品体积是菜的价格,状态转移时记录答案。
    

#include "iostream"#include "cstdlib"#include "cstring"#include "cmath"#include "algorithm"using namespace std;int max(int a,int b){    if(a>b)        return a;    else         return b;}int main(){    int i,j,m,n,a[2000],d[2000];    while( scanf("%d",&n)!=EOF && n )    {        for(i=0;i<n;i++)            scanf("%d",&a[i]);            scanf("%d",&m);        sort(a,a+n);        memset(d,0,sizeof(d));                if(m>=5)        {            {            for(i=0;i<n-1;i++)                for(j=m-5;j>=a[i];j--)                {                    d[j]=max(d[j],d[j-a[i]]+a[i]);                      }            }            printf("%d\n",m-d[m-5]-a[n-1]);        }        else             printf("%d\n",m);    }}//先计算出m-5块钱在n-1个物品内最多买多少钱的菜,然后再减去最大价格的菜


     AC  Hdu 2955 Robberies (推荐)抢劫方案最优问题,需要一个简单地转换,我们求的是不被抓的概率而非被抓的概率,各个银行的储蓄总和为背包容量,体积为单个银行 的储蓄,价值为不被抓概率。

#include "iostream"#include "cstdlib"#include "cstring"#include "cmath"#include "algorithm"using namespace std;int max(int a,int b){    if(a>b)        return a;    else        return b;}double p;int n,t,sum;int m[1000];double q[1000];double dp[10000];int main(){    scanf("%d",&t);    while(t--)    {        int ss;        sum=0;        scanf("%lf %d",&p,&n);        for(int i=0;i<n;i++)        {            scanf("%d%lf",&m[i],&q[i]);            q[i]=1.0-q[i];            sum+=m[i];        }        memset(dp,0,sizeof(dp));        dp[0]=1;        for(int i=0;i<n;i++)            for(int j=sum;j>=0;j--)            {                if(j-m[i]>=0)                dp[j]=max(dp[j],dp[j-m[i]]*q[i]);            }        for(int i=0;i<=sum;i++)        {            int big=-1;            if( dp[i]>big && ( dp[i]>=(1-p)) )            {                big=dp[i];                ss=i;            }        }        printf("%d\n",ss);                     }    }


     AC   Poj 2184 Cow Exhibition(推荐)变形的01背包,其实问题的本质是保证智商和幽默感和不为负数情况下的最大和。智商属性体积,幽默感属性为价值,问题转换为求体积大等于0时的体积、价值总和。 
     
#include "stdio.h"#include "stdlib.h"#include "algorithm"#include "iostream"#include "math.h"#include "string.h"using namespace std;#define max(a,b)    ((a)>(b)?(a):(b))  int a[110],b[110];int dp[200000];int main(){int n;int t=10000;while(scanf("%d",&n)!=EOF ){for(int i=0;i<n;i++)scanf("%d%d",&a[i],&b[i]);memset(dp,-10000,sizeof(dp));dp[t]=0;for(int i=0;i<n;i++){if(a[i]<0 && b[i]<0 )continue ;else if(a[i]>0){for(int j=199999;j>=a[i];j--)dp[j]=max(dp[j-a[i]]+b[i],dp[j]);}else{for(int j=0;j<200000+a[i];j++)dp[j]=max(dp[j-a[i]]+b[i],dp[j]);}}int ans=0;for(int i=t;i<200000;i++)if(dp[i]>0)ans=max(ans,i-t+dp[i]);printf("%d\n",ans);}return 0;}

     AC   Hdu 3466 Proud Merchants 与顺序有关的01背包,先按q-p排序再来处理,难想容易敲。

    

#include<stdio.h>#include<iostream>#include<math.h>#include<stdlib.h>#include<ctype.h>#include<algorithm>#include<vector>#include<string>#include<queue>#include<stack>#include<set>#include<map>#include <string>#include <sstream>using namespace std;int dp[100000];int max (int a,int b){    if (a>b )        return a ;    else         return b;}struct Ac{    int p;    int q;    int v;}ac[1000000];bool cmp(Ac ss ,Ac sss){    return ( ss.q-ss.p )  < ( sss.q- sss.p )  ; }int main(){    int n,m;    int t,s ,k;    while(scanf("%d%d",&n,&m)!=EOF )    {        for(int i=0;i<n;i++)            scanf("%d%d%d",&ac[i].p,&ac[i].q,&ac[i].v);        memset(dp,0,sizeof(dp));        sort(ac,ac+n,cmp);            for (int i=0;i<n;i++)                for (int j=m;j>=0;j--)                {                    if ( j-ac[i].q>=0 )                     dp[j]=max (dp[j],dp[j-ac[i].p]+ac[i].v);                 }                printf("%d\n",dp[m]);    }    return 0;}

     AC   Hdu 1114 Piggy-Bank  简单多重背包,但当成01背包来暴力也完全没有问题

#include "iostream"#include "cstdlib"#include "cstring"#include "cmath"#include "algorithm"using namespace std;int min(int a,int b){    if(a>b)        return b;    else         return a;}int main(){    int t,ok,k;    int e,f,n,s;    int p[1000],w[1000],dp[10000];    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&e,&f);        scanf("%d",&n);        for(int i=0;i<n;i++)            scanf("%d%d",&p[i],&w[i]);                memset(dp,1000000,sizeof(dp));        dp[0]=0;        s=f-e;        ok=0;        for(int i=0;i<n;i++)            for(int j=0;j<=s;j++)            {                if(j-w[i]>=0)                    dp[j]=min(dp[j],dp[j-w[i]]+p[i]);            }                                        if(dp[s]!=1000000 && dp[s]<1000000)                printf("The minimum amount of money in the piggy-bank is %d.\n",dp[s]);                else                    printf("This is impossible.\n");    }}


     AC  Hdu 1059 Dividing 简单多重背包,体积为硬币数,价值为币值,可用二进制处理成01背包求解,可用30num进行优化。

//多重背包//HDU 1059//题意:价值分别为1,2,3,4,5,6的物品的个数分别为 a[1],a[2],````a[6]//问能不能分成两堆价值相等的 #include<stdio.h>#include<string.h>int a[7];int f[120005];int v,k;void ZeroOnePack(int cost,int weight)//cost 为费用, weight 为价值 {    for(int i=v;i>=cost;i--)       if(f[i-cost]+weight>f[i]) f[i]=f[i-cost]+weight;}    void CompletePack(int cost,int weight){    for(int i=cost;i<=v;i++)        if(f[i-cost]+weight>f[i]) f[i]=f[i-cost]+weight;}         void MultiplePack(int cost ,int weight,int amount){    if(cost*amount>=v) CompletePack(cost,weight);    else    {        for(int k=1;k<amount;)        {            ZeroOnePack(k*cost,k*weight);            amount-=k;            k<<=1;        }            ZeroOnePack(amount*cost,amount*weight);    }    }    int main(){    int tol;    int iCase=0;    while(1)    {        iCase++;        tol=0;        for(int i=1;i<7;i++)        {            scanf("%d",&a[i]);            tol+=a[i]*i;//总价值数         }          if(tol==0) break;        if(tol%2==1)        {            printf("Collection #%d:\nCan't be divided.\n\n",iCase);            continue;        }              else        {            v=tol/2;            memset(f,0,sizeof(f));            for(int i=1;i<7;i++)              MultiplePack(i,i,a[i]);            if(f[v]==v)               printf("Collection #%d:\nCan be divided.\n\n",iCase);            else printf("Collection #%d:\nCan't be divided.\n\n",iCase);        }        }        return 0;    }


     AC    Hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 标题超长超简单的多重背包,可用01背包求解。

#include <stdio.h>  #include <string.h>  #include <algorithm>  using namespace std;    const int INF = 0x3f3f3f3f;  int n,m;  int c[110],w[110],num[110],dp[110];      void ZeroOnePack(int cost, int weight)   {       for(int i = n; i >= cost; i--)           dp[i] = max(dp[i],dp[i-cost]+weight);  }    void CompletePack(int cost, int weight)  {      for(int i = cost; i <= n; i++)          dp[i] = max(dp[i],dp[i-cost]+weight);    }   void MultiplePack(int cost, int weight, int amount)  {      if(cost * amount >= n)    {          CompletePack(cost,weight);      }      else   {          int k = 1;          while(k < amount)          {             ZeroOnePack(k*cost,k*weight);              amount -= k;              k = k << 1;         }          ZeroOnePack(amount*cost,amount*weight);     }  }    int main()  {      int test;      scanf("%d",&test);      while(test--)      {         scanf("%d %d",&n,&m);          for(int i = 1; i <= m; i++)         {              scanf("%d %d %d",&c[i],&w[i],&num[i]);          }           memset(dp,0,sizeof(dp));                   for(int i = 1; i <= m; i++)          {             MultiplePack(c[i],w[i],num[i]);          }         printf("%d\n",dp[n]);     }     return 0;  }  



0 0
原创粉丝点击