贪心算法——部分背包问题(贪心策略内容)

本文探讨了贪心算法的贪心选择性质和最优子结构,并通过部分背包问题进行实例解析。通过按物品单位价值从大到小排序,依次选取单位价值最大的物品装入背包,实现背包最大价值。代码实现展示了如何运用贪心策略解决部分背包问题。
 贪心策略
贪心选择性质:一个全局最优解可通过做局部最优(贪心)选择来达到。
最优子结构:如果问题的一个最优解包含了其子问题的最优解。
贪心算法与动态规划算法的差异:贪心算法和动态规划算法都要求问题具有最优子结构性质,这是两类算法的一个共同点。但是,对于一个具有最优子结构的问题应该选用贪心算法还是动态规划算法来求解?是不是能用动态规划算法求解的问题也能用贪心算法来求解?下面我们来研究两个经典的组合优化问题,并以此来说明贪心算法与动态规划算法的主要差别。
一、部分背包问题
假定有n个商品,每个商品i的重量为w[i],价值为v[i],现有一个背包,最多能装M的重量。其中(0 <= i < N, 0 < w[i] < M)。
问题:怎样装能使包中装入的商品价值最高(对于每个商品i可以只装该商品的一部分x[i])?
即对w[1]*x[1] + w[2]*x[2] + ... + w[n]*x[n] <= M
当0 <= x[i] <= 1, v[i] > 0, 1 <= i <= n时
使得v[1]*x[1] + v[2]*x[2] + ... + v[n]*x[n]取得最大。

KnapsackMain.c
/*
 * Copyright@2008,cn.edu.seu.cose
 * All rights reserverd.
 * 
 * Author:Greentea
 * Date:08.02.11
 
*/

#include 
<stdio.h>
#include 
<stdlib.h>

typedef 
struct ElemType{
    
int *index;        /*物品编号*/
    
int length;        /*物品数*/
    
float *w;        /*物品重量*/
    
float *v;        /*物品价值*/
    
float *r;        /*物品的单位价值*/
    
float *x;        /*物品所取量[0, 1]*/
}
Elem;

Elem 
*InitElem(int *index, float *w, float *v, float *r, float *x, int n)
{
    
int i;
    Elem 
*e;
    
    e 
= (Elem *)malloc(n * sizeof(Elem));
    e
->index = (int *)malloc(n * sizeof(int));
    e
->= (float *)malloc(n * sizeof(float));
    e
->= (float *)malloc(n * sizeof(float));
    e
->= (float *)malloc(n * sizeof(float));
    e
->= (float *)malloc(n * sizeof(float));
    
    
for(i = 0; i < n; i++)
    
{
        e
->index[i] = index[i];
        e
->v[i] = v[i];
        e
->w[i] = w[i];
        e
->r[i] = v[i] / w[i];
        e
->x[i] = 0.0;
    }

    e
->length = n;
    
    
return e;
}


void FreeElem(Elem **e)
{
    free((
*e)->index);
    free((
*e)->v);
    free((
*e)->w);
    free((
*e)->r);
    free((
*e)->x);
    free(
*e);
}


void PrintElem(Elem *e)
{
    
int i;
    
    
for(i = 0; i < e->length; i++)
    
{
        
if(e->x[i] != 0)
        printf(
"%d: %f ", i, e->x[i]);
    }

}

/*
 * 按物品单位价值从大到小排序,由index数组纪录排序后的顺序
 
*/

void InsertSort(Elem **e)
{
    
int i, j, n, keyind;
    
float key;
    
float *rr;
    
    n 
= (*e)->length;
    rr 
= (float *)malloc(n * sizeof(float));
    
for(i = 0; i < n; i++)
    
{
        rr[i] 
= (*e)->r[i];
    }

    
for(j = 1; j < n; j++)
    
{
        key 
= rr[j];
        keyind 
= j;
        i 
= j - 1;
        
while((i >= 0&& (rr[i] < key))
        
{
            rr[i
+1= rr[i];
            (
*e)->index[i+1= (*e)->index[i];
            i
--;
        }

        rr[i
+1= key;
        (
*e)->index[i+1= keyind;
    }

    free(rr);
}


/*
 * c:背包容量
 * 依次选取单位重量价值最大的物品
 
*/

float Knapsack(Elem *e, int c)
{
    
int i, n;
    
float total;
    
    n 
= e->length;
    InsertSort(
&e);
    total 
= 0;
    
for(i = 0; i < n; i++)
    
{
        e
->x[i] = 0;
    }

    
for(i = 0; i < n; i++)
    
{
        
if(e->w[e->index[i]] > c) break;
        e
->x[e->index[i]] = 1;
        total 
+= e->v[e->index[i]];
        c 
-= e->w[e->index[i]];
    }

    
if(i < n)
    
{
        e
->x[e->index[i]] = c / e->w[e->index[i]];
        total 
+= e->x[e->index[i]] * e->v[e->index[i]];
    }

    
return total;
}


int main(int argc, char **argv)
{
    
float w[] = {35306050401025};
    
float v[] = {10403050354030};
    
float r[] = {0000000};
    
float x[] = {0000000};
    
int index[] = {0123456};
    
int n = 7;
    Elem 
*elem;
    
int c = 150;
    
    elem 
= InitElem(index, w, v, r, x, n);
    printf(
"Total Value:%f ", Knapsack(elem, c));
    PrintElem(elem);
    FreeElem(
&elem);
    
    
return 0;
}


0/1背包问题
问题同上,只是每次取时,x[i]只能取值0或1。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值