思想:
如果一个问题是由交叠的子问题所构成,那么我们就可以用动态规划技术来解决它。一般来说,这样的子问题出现在对给定问题求解的递归关系中。这个递推关系包含了相
同问题的更小子问题的解。动态规划法建议,与其对交叠子问题一次又一次的求解,不如把每个较小子问题只求解一次并把结果记录在表中。
例题:0-1背包问题
问题描述:
给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
对于一种物品,要么装入背包,要么不装。所以对于一种物品的装入状态可以取0和1.我们设物品i的装入状态为xi,xi∈ (0,1),此问题称为0-11背包问题。
过程分析(通过一个例子):
数据:物品个数n=5,物品重量w[n]={0,2,2,6,5,4},物品价值V[n]={0,6,3,5,4,6}, (第0位,置为0,不参与计算,只是便于与后面的下标进行统一,无特别用处,也可不这么处理。)总重量c=10. 背包的最大容量为10,那么在设置数组m大小时,可以设行列值为6和11,那么,对于m(i,j)就表示可选物品为i…n背包容量为j(总重量)时背包中所放物品的最大价值。
对于一种物品,要么装入背包,要么不装。所以对于一种物品的装入状态可以取0和1.我们设物品i的装入状态为xi,xi∈ (0,1),此问题称为0-11背包问题。
过程分析(通过一个例子):
数据:物品个数n=5,物品重量w[n]={0,2,2,6,5,4},物品价值V[n]={0,6,3,5,4,6}, (第0位,置为0,不参与计算,只是便于与后面的下标进行统一,无特别用处,也可不这么处理。)总重量c=10. 背包的最大容量为10,那么在设置数组m大小时,可以设行列值为6和11,那么,对于m(i,j)就表示可选物品为i…n背包容量为j(总重量)时背包中所放物品的最大价值。
![](https://img-my.csdn.net/uploads/201204/15/1334501887_1644.png)
下面是自己写的代码:
#include<stdio.h>
#include<malloc.h>
#define MAX(X, Y) X > Y ? X : Y
void calaccount(int minnum, int** account, int num, int* weight, int *value, int maxweight);
void getaccount(int** account, int num, int* weight, int *value, int maxweight);
void printaccount(int **account, int num, int maxweight);
void search(int **account, int maxweight, int num, int *weight);
int main()
{
int *value, *weight; //背包质量和价值
int maxweight; //可承载最大重量
int **account; //记录矩阵
int num; //背包数量从零开始
int i;
printf("please input the num of bag\n");//背包数
scanf("%d", &num);
printf("please input the max weight\n");
scanf("%d", &maxweight);
value = (int*)malloc(sizeof(int)*(num)); //存储背包的价值
weight = (int*)malloc(sizeof(int)*(num));//存储背包的重量
account = (int**)malloc(sizeof(int*)*num); //矩阵
for(i = 0; i < num; i++)
account[i] = (int*)calloc(maxweight+1, sizeof(int));
printf("please input the %d weights\n", num);
for(i = 0; i < num; i++)
scanf("%d", &weight[i]);
printf("please input the %d values\n", num);
for(i = 0; i < num; i++)
scanf("%d", &value[i]);
getaccount(account, num, weight, value, maxweight);
printaccount(account, num, maxweight);
search(account, maxweight, num, weight);
return 0;
}
void calaccount(int minnum, int** account, int num, int* weight, int *value, int maxweight)//计算一行
{
for(; maxweight >= 0; maxweight--) {
if(minnum == num - 1) {
if(weight[minnum] > maxweight)
account[minnum][maxweight] = 0;
else
account[minnum][maxweight] = value[minnum];
} else if(weight[minnum] > maxweight) {
account[minnum][maxweight] = account[minnum+1][maxweight];
} else
account[minnum][maxweight] = MAX((account[minnum+1][maxweight]),(account[minnum+1][maxweight-weight[minnum]] + value[minnum]));
}
}
void getaccount(int** account, int num, int* weight, int *value, int maxweight) //驱动程序
{
int mweight;
int i;
for(i = num-1; i >= 0; i--)
calaccount(i, account, num, weight, value, maxweight);
}
void printaccount(int **account, int num, int maxweight) //打印矩阵
{
int weight;
int i = 0;
for(; i < num; i++) {
for(weight = 0; weight <= maxweight; weight++)
printf("%d ", account[i][weight]);
printf("\n");
}
}
void search(int **account, int maxweight, int num, int *weight) //输出最佳组合
{
int i = 0;
int max = 0;
printf("the total value is %d\n", account[0][maxweight]);
printf("the best combination is ");
while(maxweight > 0 & i < num - 1) {
if(account[i][maxweight] != account[i+1][maxweight]) {
printf("%d ", i);
maxweight -= weight[i];
}
i++;
}
if(account[i][maxweight] != 0)
printf("%d", i);
printf("\n");
}