动态规划问题

思想:

        如果一个问题是由交叠的子问题所构成,那么我们就可以用动态规划技术来解决它。一般来说,这样的子问题出现在对给定问题求解的递归关系中。这个递推关系包含了相

同问题的更小子问题的解。动态规划法建议,与其对交叠子问题一次又一次的求解,不如把每个较小子问题只求解一次并把结果记录在表中。

例题: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(总重量)时背包中所放物品的最大价值。

下面是自己写的代码:

#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");
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值