01背包(回溯法)

01背包,即只判断物品取舍,让利益最大化
经过老师的讲解,我了解到

n=3, C=30, w={16, 15, 15}, v={45, 25, 25}
开始时,Cr=C=30,V=0,A为唯一活结点,也是当前扩展结点
1.

扩展A,先到达B结点 再扩展B到达E(续) E可行,此时A、B、E是活结点,E成为新的扩展结点 扩展E,先到达J Cr K不可扩展,成为死结点,返回到E E没有可扩展结点,成为死结点,返回到B B没有可扩展结点,成为死结点,返回到A

2.

A再次成为扩展结点,扩展A到达C Cr=30,V=0,活结点为A、C,C为当前扩展结点 扩展C,先到达F
Cr=Cr-w2=15,V=V+v2=25,此时活结点为A、C、F,F成为当前扩展结点 扩展F,先到达L
Cr=Cr-w3=0,V=V+v3=50 L是叶结点,且50>45,皆得到一个可行解x=(0,1,1),V=50
L不可扩展,成为死结点,返回到F 再扩展F到达M M是叶结点,且25<50,不是最优解 M不可扩展,成为死结点,返回到F
F没有可扩展结点,成为死结点,返回到C

3.

再扩展C到达G Cr=30,V=0,活结点为A、C、G,o为当前扩展结点
扩展G,先到达N,N是叶结点,且25<50,不是最优解,又N不可扩展,返回到G
再扩展G到达O,O是叶结点,且0<50,不是最优解,又O不可扩展,返回到G G没有可扩展结点,成为死结点,返回到C
C没有可扩展结点,成为死结点,返回到A A没有可扩展结点,成为死结点,算法结束,最优解X=(0,1,1),最优值V=50

01背包(回溯法)_第1张图片01背包(回溯法)_第2张图片
如下是根据我自行理解写的代码部分

#include
int n,c,bestv;//物品的个数,背包的容量,最大价值
int v[10000],w[10000],x[10000],bestx[10000];//物品的价值,物品的重量,x[i]暂存物品的选中情况,物品的选中情况

void Backtrack(int i,int cv,int cw)
{ //cv当前包内物品重量,cp当前包内物品价值
    int j;
    if(i>n)//回溯结束
    {
        if(cv>bestv)
        {
            bestv=cv;
            for(i=0;i<=n;i++) bestx[i]=x[i];
        }
    }
    else
        for(j=0;j<=1;j++)
        {
            x[i]=j;
            if(cw+x[i]*w[i]<=c)
            {
                cw+=w[i]*x[i];
                cv+=v[i]*x[i];
                Backtrack(i+1,cv,cw);
                cw-=w[i]*x[i];
                cv-=v[i]*x[i];
            }
        }
}

int main()
{
    int i;
    bestv=0;
    printf("请输入物品个数:\n");
    scanf("%d",&n);
    printf("请输入背包最大容量:\n");
    scanf("%d",&c);
	printf("请依次输入物品的重量:\n");
    for(i=1;i<=n;i++)
        scanf("%d",&w[i]);
    printf("请依次输入物品的价值:\n");
    for(i=1;i<=n;i++)
        scanf("%d",&v[i]);
    Backtrack(1,0,0);
    printf("最大价值为:\n");
    printf("%d\n",bestv);
    printf("被选中的物品依次是(0表示未选中,1表示选中)\n");
    for(i=1;i<=n;i++)
        printf("%d ",bestx[i]);
    return 0;
}

你可能感兴趣的:(算法,#C语言,#回溯法)