01背包问题 -- 回溯法 1

/*0-1背包回溯法实现*/
#include <stdio.h>
#include <conio.h>
int n;				//物品数量
double c;			//背包容量
double v[100];		//各个物品的价值
double w[100];		//各个物品的重量
double cw = 0.0;		//当前背包重量
double cp = 0.0;		//当前背包中物品价值
double bestp = 0.0;	//当前最优价值
double perp[100];	//单位物品价值排序后
int order[100];		//物品编号
int put[100];			//设置是否装入
/*按单位价值排序*/
void knapsack()
{
    int i,j;
    int temporder = 0;
    double temp = 0.0;
    for(i=1;i<=n;i++)
        perp[i]=v[i]/w[i];
    for(i=1;i<=n-1;i++)
    {
        for(j=i+1;j<=n;j++)
            if(perp[i]<perp[j]) //冒泡排序perp[],order[],sortv[],sortw[]
        {
            temp = perp[i];
            perp[i]=perp[i];
            perp[j]=temp;
            temporder=order[i];
            order[i]=order[j];
            order[j]=temporder;
            temp = v[i];
            v[i]=v[j];
            v[j]=temp;
            temp=w[i];
            w[i]=w[j];
            w[j]=temp;
        }
    }
}
/*回溯函数*/
void backtrack(int i)
{
    double bound(int i);
    if(i>n)
    {
        bestp = cp;
        return;
    }
    if(cw+w[i]<=c)
    {
        cw+=w[i];
        cp+=v[i];
        put[i]=1;
        backtrack(i+1);
        cw-=w[i];
        cp-=v[i];
    }
    if(bound(i+1)>bestp)  //符合条件搜索右子数
        backtrack(i+1);
}
/*计算上界函数*/
double bound(int i)
{
    double leftw= c-cw;
    double b = cp;
    while(i<=n&&w[i]<=leftw)
    {
        leftw-=w[i];
        b+=v[i];
        i++;
    }
    if(i<=n)
        b+=v[i]/w[i]*leftw;
    return b;
}
int main()
{
    int i;
    printf("请输入物品的数量和容量:");
    scanf("%d %lf",&n,&c);
    printf("请输入物品的重量和价值:\n");
    for(i=1;i<=n;i++)
    {
        printf("第%d个物品的重量:",i);
        scanf("%lf",&w[i]);
        printf("价值是:");
        scanf("%lf",&v[i]);
        order[i]=i;
    }
    knapsack();
    backtrack(1);
    printf("最优价值为:%lf\n",bestp);
    printf("需要装入的物品编号是:");
    for(i=1;i<=n;i++)
    {
        if(put[i]==1){
            printf("%d ",order[i]);	
		}
    }
	printf("\n");
   return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/zili/p/9905940.html
今日推荐