文章目录
- 前言
- 一、什么是01背包问题?
- 二、解决方法
- 1.动态规划法
- 2.回溯法
- 总结
前言
背包问题是算法学习的经典问题,背包问题又在不同的问题条件下可以用到不同的算法,如0-1背包,完全背包(硬币找零 硬币数无限制),多重背包(硬币找零 硬币数有限制),分数背包等。我们可以通过不同的背包问题来学习算法,本文章主要探讨01背包问题的求解方法。
一、什么是01背包问题?
问题描述:给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi,背包最大承载重量为C。物品是不可分割的,应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
二、解决方法
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int N=10;
const int bag=N*2;
const int MAXSIZE=100000;
struct goods{
int w;//重量
int v;//价值
}g[N];
int max_value=0;
int count=0;
int a[N],r[N+1],dp[N][bag+1],x[N];
int main()
{
int i,start,end;
for(i=0;i<N;i++){
g[i].v=rand()%5+1;
g[i].w=rand()%5+1;
printf("物品%d,价值%d,重量%d\n",i,g[i].v,g[i].w);
}
r[N]=0;
for(i=N-1;i>=0;i--){
r[i]=r[i+1]+g[i].v;
}
printf("回溯能获得的最大价值为:%d\n",huisu(0,0,0));
printf("找到一种最佳方案:");huisuxunzhao();printf("\n");
printf("动态规划能获得的最大价值为:%d\n",guihua());
printf("找到一种最佳方案:");guihuaxunzhao();printf("\n");
return 0;
}
1.动态规划法
代码如下(示例):
int guihua()
{
for(int i=0;i<N;i++)
for(int j=0;j<=bag;j++){
if(i==0&&g[i].w>j)
dp[i][j]=0;
else if(i==0&&g[i].w<=j)
dp[i][j]=g[i].v;
else if(j==0)
dp[i][j]=0;
else if(g[i].w>j)
dp[i][j]=dp[i-1][j];
else
dp[i][j]=dp[i-1][j]>(dp[i-1][j-g[i].w]+g[i].v)?dp[i-1][j]:(dp[i-1][j-g[i].w]+g[i].v);
}
return dp[N-1][bag];
}
void guihuaxunzhao()
{
int i=N-1,j=bag;
while(1){
if(i>0){
if(dp[i-1][j]<(dp[i-1][j-g[i].w]+g[i].v)){
printf("%d ",i);
j=j-g[i].w;
i--;
}
else{
i--;
}
}
else if(i==0){
if(j>=g[i].w){
printf("%d ",i);
break;
}
else
break;
}
}
}
2.回溯法
代码如下(示例):
int huisu(int t,int now_v,int now_w)
{
if(t==N){
if(now_w<=bag&&now_v>max_value){
max_value=now_v;
for(int j=0;j<N;j++){
x[j]=a[j];
}
}
}
else{
for(int i=0;i<=1;i++){
a[t]=i;
now_v=now_v+g[t].v*i;
now_w=now_w+g[t].w*i;
if(now_w<=bag&&now_v+r[t+1]>=max_value)
huisu(t+1,now_v,now_w);
}
}
return max_value;
}
void huisuxunzhao()
{
int w=0;
for(int i=N-1;i>=0;i--){
if(x[i]==1){
printf("%d ",i);
}
}
}
总结
以上就是解决01背包问题的两种方法,01背包还可以用分支限界法解决,读者可以自己思考。