void zero(int w,int v)//01 { for(int i=m;i>=w;i--)dp[i]=max(dp[i],dp[i-w]+v); } void com(int w,int v)//完全 { for(int i=w;i<=m;i++)dp[i]=max(dp[i],dp[i-w]+v); } void multi(int w,int v,int c)//多重(可看成完全和01组成/混合又可看成它们3种组成 { if(c*w>=m) { com(w,v); return; } int k=1; while(k<c)//二进制优化 例题tzoj 5736 { zero(k*w,k*v); c=c-k; k=k*2; } zero(c*w,c*v); }
01背包 (取或不取这件)
int n,i,j,m,w[35],v[35],dp[205];// 最多30个物品,最大容量m=200
cin>>m>>n;
for(i=1;i<=n;i++)cin>>w[i]>>v[i];//重量,价值
for(i=1;i<=n;i++)
for(j=m;j>=w[i];j--)//逆序
dp[j]=max(dp[j-w[i]]+v[i],dp[j]);
cout<<dp[m]<<endl;
void ZeroOnePack()//dp【x】:表示 和为x的方案数 { memset(dp,0,sizeof(dp)); dp[0]=1; for(int i=0;i<n;i++){ for(int j=maxS-1;j>=s[i];j--){ dp[j]+=dp[j-s[i]]; } } }
完全背包(一件东西有无限件,可以取无限次)
int n,m,i,j,w[32],c[32],dp[202];
scanf("%d%d",&m,&n);//容量,种数
for(i=1;i<=n;i++)cin>>w[i]>>v[i];//重量,价值
for(i=1;i<=n;i++)
for(j=w[i];j<=m;j++)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
printf("max=%d",dp[m]);
多重背包:(toj 5740)
for(i=1;i<=n;i++)
for(k=0;k<mun[i];k++)//每种的个数 (attention 没有等于号)
for(j=m;j>=w[i];j--) dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
二维费用流背包:(toj 5742)
注意if 和 初始化 和 到0
#include<bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f int n,m,k,a[1005],b[1005],w[1005],dp[22][80]; int main() { int i,j,q; cin>>m>>n; cin>>k; for(i=1;i<=k;i++)cin>>a[i]>>b[i]>>w[i]; for(i=0;i<=m;i++) for(j=0;j<=n;j++)dp[i][j]=INF;//刚好装满 dp[0][0]=0; for(i=1;i<=k;i++) for(j=m;j>=0;j--)//注意要到0 ///////////////////////////////// for(q=n;q>=0;q--) { int t1=j-a[i],t2=q-b[i];////////////////注意这些if语句 if(t1>m)t1=m; if(t2>n)t2=n; if(t1<0)t1=0; if(t2<0)t2=0; dp[j][q]=min(dp[j][q],dp[t1][t2]+w[i]); } cout<<dp[m][n]<<endl; }
分组背包:(toj 5743)
#include<bits/stdc++.h> using namespace std; int n,V,t,w[31],c[31],a[11][31],dp[202]; int main() { int i,j,k; cin>>V>>n>>t; for(i=1;i<=n;i++) { int p; cin>>w[i]>>c[i]>>p; a[p][++a[p][0]]=i; //a[p][0]存储p组元素个数,a[p][x] 是存储元素序号 }//a[p][x] p组第x个 for(i=1;i<=t;i++) { for(j=V;j>=0;j--) { for(k=1;k<=a[i][0];k++) { int te=a[i][k]; if(j>=w[te])dp[j]=max(dp[j],dp[j-w[te]]+c[te]); } } } cout<<dp[V]<<endl; }