算法 0-1背包问题

来源:互联网 发布:gbk转utf8 linux 编辑:程序博客网 时间:2024/05/30 23:40

题目

给定n种物品和一个背包。物品i的重量是wi,价值是vi,背包的容量为c。
问应如何选择装入背包的物品,使装入背包中物品的总价值最大?
分别使用回溯法和动态规划编码。


分析

m[i][j]={ max{ m[i-1][j],m[i-1][j-wi]+vi } } 其中wi<=j
m[i][j]=m[i-1][j] 其中 wi>j>0


回溯法:

#include <stdio.h>    #include <math.h>   #define n 5 //物品数#define c 10 //背包最大容量int w[n]={2,2,6,5,4};//物品的重量int v[n]={6,3,5,4,6};//物品的价值int x[n]={0};int bestx[n]={0};int tempW;//当前重量int tempV;//当前价格int maxValue;void dfs(int t){     if(t>=n){        if(tempV>maxValue){            maxValue=tempV;            for(int i=0; i<n; i++)                  bestx[i]=x[i];          }        return;    }    for(int i=0; i<=1; i++){        x[t]=i;        //不装        if(x[t]==0){            dfs(t+1);            x[t]=0;        }        //装        if(tempW+w[t]<=c && x[t]==1){            tempW+=w[t];            tempV+=v[t];            dfs(t+1);            x[t]=0;            tempW-=w[t];            tempV-=v[t];            }    }   }int main(){      dfs(0);      printf("%d\n",maxValue);    for(int i=0; i<n; i++){        printf("%d\t",bestx[i]);    }    return 0;    }    

动态规划:

#include<stdio.h>#define n 5int w[n]={2,2,6,5,4};//物品的重量int v[n]={6,3,5,4,6};//物品的价值int x[n];//物品的选取状态,选中则是1,没选中为0int c=10;//背包最大容量int V[100][100]={0};//前i个物品装入容量为j的背包中获得的最大价值int getMax(int a,int b){      return a>b?a:b;}void suanfa(){    int i,j;    for(i=0; i<n; i++){        for(j=0; j<=c; j++){            if(j<w[i])//小于                V[i][j]=V[i-1][j];            else//大于                V[i][j]=getMax(V[i-1][j],V[i-1][j-w[i]]+v[i]);        }    }    j=c;    for(i=n-1; i>=0; i--){        if(V[i][j]>V[i-1][j]){            x[i]=1;            j=j-w[i];        }else            x[i]=0;       }    printf("选中的物品下标:\n");    for(i=0; i<n; i++)        printf("%d\t",x[i]);    printf("\n最优值:%d\n",V[n-1][c]); }int main(){    suanfa();    return 0;   }
0 0