01背包进阶 二维数组/滚动数组 模/滚动数组 异或/一维数组
枚举所有物品能想到,但编写就很困难了。故需寻求01背包固定算法
1.二维数组写法
#include <stdio.h>
int f[35][210],w[35],c[35];
int max(int a,int b){
return a>b?a:b;
}
int main(){
int M,N,i,j;
scanf("%d%d",&M,&N);
for(i=1;i<=N;i++)scanf("%d%d",&w[i],&c[i]);
for(i=1;i<=N;i++)
for(j=0;j<=M;j++){
f[i][j]=f[i-1][j];
if(j>=w[i])f[i][j]=max(f[i][j],f[i-1][j-w[i]]+c[i]);
}
printf("%d\n",f[N][M]);
return 0;
}
2.1滚动数组写法一 模
#include <stdio.h>
#include <string.h>
int w[35],c[35],f[2][210];
int max(int a,int b){
return a>b?a:b;
}
int main(){
int m,n,i,j;
memset(f,0,sizeof(f));
scanf("%d%d",&m,&n);
for(i=1;i<=n;i++)
scanf("%d%d",&w[i],&c[i]);
for(i=1;i<=n;i++)
for(j=0;j<=m;j++){
f[i%2][j]=f[(i-1)%2][j];
if(j>=w[i])f[i%2][j]=max(f[(i-1)%2][j],f[(i-1)%2][j-w[i]]+c[i]);
}
printf("%d\n",f[n%2][m]);
return 0;
}
2.2滚动数组写法二 异或
#include <stdio.h>
#include <string.h>
int w[35],c[35],f[2][210];
int max(int a,int b){
return a>b?a:b;
}
int main(){
int m,n,i,j,k=0;
memset(f,0,sizeof(f));
scanf("%d%d",&m,&n);
for(i=1;i<=n;i++)
scanf("%d%d",&w[i],&c[i]);
for(i=1;i<=n;i++){
k^=1;//特别注意此行,容易写错位置
for(j=0;j<=m;j++){
f[k][j]=f[k^1][j];
if(j>=w[i])f[k][j]=max(f[k^1][j],f[k^1][j-w[i]]+c[i]);
}
}
printf("%d\n",f[k][m]);
return 0;
}
3.一维数组写法,建议学习此法前,先学习此文从01背包进化到完全背包之后会有更深刻的理解
#include <stdio.h>
#include <string.h>
int w[35],c[35],f[210];
int max(int a,int b){
return a>b?a:b;
}
int main(){
int m,n,i,j;
memset(f,0,sizeof(f));
scanf("%d%d",&m,&n);
for(i=1;i<=n;i++)
scanf("%d%d",&w[i],&c[i]);
for(i=1;i<=n;i++)
for(j=m;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+c[i]);
printf("%d\n",f[m]);
return 0;
}