蓝桥杯 01背包 记忆话数组
有n个重量和价值分别为wi,vi的物品。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值
/**
*首先动态记录第i个物品,和总重量小于j的部分
*并且将已经接受过的记录动态的保存在记忆化数组中
*/
#include<stdio.h>
#include<string.h>
int N,W;
int w[100],v[100];
//使用记忆化数组
int dp[100][100];
int max(int n,int m){
return n>m?n:m;
}
//从第i个物品开始挑选总重小于j的部分
int rec(int i,int j){
//如果当前位置存入数据,则直接返回该数据
if(dp[i][j]>=0) return dp[i][j];
//记录当前物品重量
int res;
//当最后一个物品选择完成之后,可以添加的重量为0
if(i==N) res=0;
//如果当前物品重量大于可添加的重量,当前物品不可以选择
else if(w[i]>j) res=rec(i+1,j);
else
//选择出选这个物品,或者不选择这个物品的最大重量
res=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);
//返回最后物品的最大重量
//保存已经记录过的数据
return dp[i][j]=res;
}
int main(){
while(scanf("%d%d",&N,&W)==2){
memset(dp,-1,sizeof(dp));
for(int i=0;i<N;i++)
scanf("%d%d",&w[i],&v[i]);
printf("%d\n",rec(0,W));
}
return 0;
}
/************************************************第2种写法,递推表达式****************************************************/
#include<stdio.h>
#include<string.h>
int N,W;
int v[100],w[100];
//dp为协助数组
int dp[100][100];
int max(int n,int m){
return n>m?n:m;
}
void rec(){
//从最后一个背包开始选择
//利用 i表示第i个背包
for(int i=N-1;i>=0;i--)
//j表示,总重量小于j的部分
for(int j=0;j<=W;j++){
if(j<w[i]) dp[i][j]=dp[i+1][j];
else{
dp[i][j]=max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]);
}
}
printf("%d\n",dp[0][W]);
}
int main(){
while(scanf("%d%d",&N,&W)==2){
memset(dp,-1,sizeof(dp));
for(int i=0;i<N;i++)
scanf("%d%d",&w[i],&v[i]);
rec();
}
return 0;
}
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。