【背包模板】

来源:互联网 发布:net编程教训 编辑:程序博客网 时间:2024/05/17 22:40
int V;//容量  //01void zeroone(int cost,int val){//费用,价值      int i;      for(i=V;i>=cost;i--){          if(dp[i]<dp[i-cost]+val){              dp[i] = dp[i-cost]+val;          }      }  }  //完全背包void complete(int cost,int val){//费用,价值      int i;      for(i=cost;i<=V;i++){          if(dp[i]<dp[i-cost]+val){              dp[i] = dp[i-cost]+val;          }      }  }  //多重背包void multi(int cost,int val,int cnt){//费用,价值,数量      if(cost*cnt>=V){          complete(cost,val);          return ;      }      int k = 1;      while(k<cnt){          zeroone(k*cost,k*val);          cnt -= k;          k *= 2;      }      zeroone(cnt*cost,cnt*val);  }  //混合三种背包:for(i=0;i<m;i++){    scanf("%d%d%d%d",&v,&weight,&value,&n);    if(v>V || weight>W)        continue;    if(n==1)        zeroone(v,weight,value);    else if(n==0)        complete(v,weight,value);    else        multiply(v,weight,value,n);}//二维费用的背包:void zeroone(int v,int weight,int value){    int i,j;    for(i=V;i>=v;i--)        for(j=W;j>=weight;j--)            if(dp[i][j]<dp[i-v][j-weight]+value)                dp[i][j]=dp[i-v][j-weight]+value;}void complete(int v,int weight,int value){    int i,j;    for(i=v;i<=V;i++)        for(j=weight;j<=W;j++)            if(dp[i][j]<dp[i-v][j-weight]+value)                dp[i][j]=dp[i-v][j-weight]+value;}void multiply(int v,int weight,int value,int count){    if(v*count>=V || weight*count>=W){        complete(v,weight,value);        return;    }    int k=1;    while(k<count){        zeroone(k*v,k*weight,k*value);        count-=k;        k*=2;    }    zeroone(count*v,count*weight,count*value);}//分组背包:for(i=1;i<=n;i++){  //枚举组    for(j=m;j>=1;j--){ //背包容量        for(k=1;k<=m;k++){ //不同费用的物品            if(j>=k)         //转移方程有j-k,要保证j-k>=0                dp[j] = max(dp[j],dp[j-k]+a[i][k]);        }    }}



















原创粉丝点击