您的位置:首页 > 其它

背包问题小结--持续更新 算法基础篇(七)

2012-06-16 11:14 369 查看
View Code

// 背包问题.cpp : 定义控制台应用程序的入口点。
//
//来自背包九讲

/****************************/
/*
设计者:cslave
代码说明:  背包问题
*/
#include "stdafx.h"
#include <iostream>
using namespace std;
#define NumItem 10
#define Max 100
typedef int CapType;
typedef int ValueType;
CapType Capacity=Max;

ValueType f[NumItem][Capacity];
CapType   Cost[NumItem];
ValueType Weight[NumItem];
int       Amount[NumItem];

/*****************01背包问题**************************/
/*
题目:有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

状态转移方程:

用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:

f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}

时间和空间复杂度均为O(VN)

伪代码:
procedure ZeroOnePack(cost,weight)
for v=V..cost
f[v]=max{f[v],f[v-cost]+weight}

procedure Pack(cost[],weight[])
for i=1..N
ZeroOnePack(c[i],w[i]);

*/
/******************分割线***************************/
void ZeroOnePack(CapType Cost,ValueType Weight)
{
for(CapType v=Capcity;v>=Cost;v--)
f[v]=f[v]>f[v-Cost]+Weight?f[v]:f[v-Cost]+Weight;
}

void Pack()
{
for(int i=0;i<NumItem;i++)
ZeroOnePack(Cost[i],Weight[i]);
}

/***********************完全背包问题***************************/
/*
题目:有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。
求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

状态转移方程:
用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:

f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k*c[i]<=v}

时间复杂度O(VN)

伪代码:
for i=1..N
for v=0..V
f[v]=max{f[v],f[v-cost]+weight}

*/
/************************分割线*********************************/
void CompletePack(CapType Cost,ValueType Weight)
{
for(CapType v=Cost;v<=Capcity;v++)
f[v]=f[v]>f[v-Cost]+Weight?f[v]:f[v-Cost]+Weight;
}

void Pack()
{
for(int i=0;i<NumItem;i++)
CompletePack(Cost[i],Weight[i]);
}

/*************************多重背包********************************/
/*
题目:有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。
求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

状态转移方程:
这题目和完全背包问题很类似。基本的方程只需将完全背包问题的方程略微一改即可,因为对于第i种物品有n[i]+1种策略:
取0件,取1件……取n[i]件。令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值,则有状态转移方程:

f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k<=n[i]}

复杂度是O(V*Σn[i])。

伪代码:
procedure MultiplePack(cost,weight,amount)
if cost*amount>=V
CompletePack(cost,weight)
return
integer k=1
while k<amount
ZeroOnePack(k*cost,k*weight)
amount=amount-k
k=k*2
ZeroOnePack(amount*cost,amount*weight)

procedure Pack(cost[],weight[])
for i=1..N
MultiplePack(c[i],w[i]);

*/

/*************************分割线***********************************/
void MultiplePack(CapType Cost,ValueType Weight,int Amount)
{
if (Cost*Amount>=Capacity)
{
CompletePack(Cost,Weight);
return;
}
int k=1;
while(k<Amount)
{
ZeroOnePack(k*Cost,k*Weight);
Amount=Amount-k;
k=k*2;
}
ZeroOnePack(Amount*Cost,Amount*Weight);
}

void Pack(CapType Cost[],ValueType weight[])
{
for(int i=0;i<NumItem;i++)
MultiplePack(cost[i],Weight[i],Amount[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: