您的位置:首页 > 其它

01背包问题

2011-09-21 20:31 357 查看
(DP)01背包问题

/*

* =====================================================================================

*

* Filename: Bag01.c

*

* Description: 01背包问题

* 有N个物品, 重量分别为w1到wn,价值分别为v1到vn,有一个承重为C的包,问该将哪些物品放入包

* 中可使得包中物品的价值和最大, 设m[i][j]代表在承重为j,可供装包的物品编号为从i(包括i)

* 到N时的最大价值(物品的最小编号为1),则此时递推公式为

* m[i][j] = max(m[i+1][j], m[i+1][j-wi] + vi) //两种情况:取物品i和不取物品i,从这两种情况中取最大值

* Version: 1.0

* Created: 2010年08月25日 08时59分40秒

* Revision: none

* Compiler: gcc

*

* Author: glq2000 (), glq2000@126.com

* Company: HUE ISRC

*

* =====================================================================================

*/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define MAX(A,B) (((A)>(B))?(A):(B))

#define N 7 //物品个数

#define C 19 //包的承重

int w[N+1] = {0, 3, 7, 2, 4, 8, 10, 5}; //w[i]:物品i的重量,
简单起见,w[0]不使用

int v[N+1] = {0, 2, 10, 3, 5, 7, 12, 6};//v[i]:物品i的价值,
简单起见,v[0]不使用

int m[N+1][C+1];//加1的目的是为了使用方便,m[i][j]表示在承重为j,可供装包的物品编号为从i(包括i)到N时的最大价值(物品的最小编号为1)

void MaxBagValue(int (*m)[C+1], int n, int c, int *w, int *v); //计算m[i][j]数组

void Output(int (*m)[C+1]); //输出m[i][j]数组

void TraceBack(int (*m)[C+1]); //求出被选择的物品的编号

int main()

{

MaxBagValue(m, N, C, w, v);

Output(m); printf("\n\n\n\n");

printf("MaxBagValue: %d\n\n", m[1][C]);

TraceBack(m);

return 0;

}

/*

*m[i][j]表示在承重为j,可供装包的物品编号为从i(包括i)到N时的最大价值(物品的最小编号为1)

*w[i] 重量, v[i] 价值, c当前包中剩余承重, n 当前可供装包的编号为从n(包括n)到N

*/

void MaxBagValue(int (*m)[C+1], int n, int c, int *w, int *v)

{

int i, j;

for(j=1; j<=c; ++j)

if(j >= w[N])

m[N][j] = v[N];

for(i=n-1; i>=1; --i)

{

for(j=1; j<=c; ++j)

if(j >= w[i])

m[i][j] = MAX(m[i+1][j], m[i+1][j-w[i]]+v[i]);

else

m[i][j] = m[i+1][j];

}

}

void Output(int (*m)[C+1]) //输出m[i][j]数组

{

int i,j;

for(i=1; i<=N; ++i)

{

printf("w[%d]=%d ", i, w[i]);

}

printf("\n");

for(i=1; i<=N; ++i)

{

printf("v[%d]=%d ", i, v[i]);

}

printf("\n\n");

for(i=0; i<=N; ++i)

{

for(j=0; j<=C; ++j)

{

printf("m[%d][%d]=%d ", i, j, m[i][j]);

}

printf("\n\n");

}

}

//利用m数组求出哪些编号的物品被选中了

void TraceBack(int (*m)[C+1])

{

printf("Seletced: ");

int i=1,j=C;

while(j && i<=N)

{

if(i==N && j>0 && m[i][j]==v[i])

{

printf("%d ", i);

j -= w[i];

++i;

}

if(m[i][j] > m[i+1][j])

{

printf("%d ", i);

j -= w[i];

++i;

}

else

++i;

}

printf("\n");

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: