Java实现动态规划实现0-1背包问题以及C++实现动态规划实现多段图

 

动态规划算法思想:把待求解问题分解成若干个子问题,先求解子问题, 然后由这些子问题的解得到原问题的解,但动态规划求解过的子问题的结果会 被保留下来,不像递归那样每个子问题的求解都要从头开始返回求解。动态规 划求解问题的关键在于获得各个阶段子问题的递推关系式:

(1)分析原问题的最优解性质,刻画其结构特征

(2)递归定义最优值

(3)自底向上(由后向前)的方式计算最优值

(4)根据计算最优值时得到的信息,构造一个最优解。

一、动态规划实现0-1背包问题

 


public class Knapsack {
		
		public static int knapsack(int[] weight, int[] value,int maxweight){
			 
			int n = weight.length;
			//最大价值数组为maxvalue[N+1][maxWeight+1],因为我们要从0开始保存
			int[][] maxvalue = new int[n+1][maxweight + 1];
			
			//重量和物品为0时,价值为0
			for (int i = 0; i < maxweight + 1; i++) {
				maxvalue[0][i] = 0;
				
			}
			for (int i = 0; i < n + 1; i++) {
				maxvalue[i][0] = 0;
				
			}
			
			//i:只拿前i件物品(这里的i因为取了0,所以对应到weight和value里面都是i-1号位置)      
			//j:假设能取的总重量为j
			//n是物品件数
			for (int i = 1; i <= n ; i++) {
				for (int j = 1; j <= maxweight; j++) {
					//当前最大价值等于放上一件的最大价值
					maxvalue[i][j] = maxvalue[i-1][j];
					//如果当前件的重量小于总重量,可以放进去或者拿出别的东西再放进去
					if (weight[i-1] <= j) {
						//比较(不放这个物品的价值)和
						//(这个物品的价值 加上 当前能放的总重量减去当前物品重量时取前i-1个物品时的对应重量时候的最高价值)
						if(maxvalue[i-1][j - weight[i-1]] + value[i-1]>maxvalue[i-1][j]) {
							maxvalue[i][j] = maxvalue[i-1][j - weight[i-1]] + value[i-1];
						}
					}
				}
			}
			return maxvalue[n][maxweight];
		}
		
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		int weight[] = {11,7,9,12,3,10};
		int value[] = {10,5,7,9,2,12};
		int maxweight = 8;
		System.out.println(knapsack(weight, value, maxweight));
	}
}

 二、动态规划实现多段图

 

#include <iostream>
using namespace std;

#define N 12+1	//结点数——为了实现方便,使结点编号和数组下标一致
#define K 5			//段数
#define INF 1000	
int c[N][N];			//c[i][j]表示i到j的花费
int cost[N];			//cost[i]表示到结点i的最小花费
int d[N];				//d[i]表示由结点i指向的最小成本边的另一端的结点
int P[K];				//每一阶段最短路径成本

void init();
void fGraph();
int main(int argc, char *argv[])
{
	init();				//初始化
	fGraph();
	int k = K;
	int sum = 0;
	int n = N - 1;
	while (k != 1)//遍历每个阶段的最短路径成本
	{
		sum += cost[n];
		n = d[n];
		k--;
	}
	cout << "最小成本路径为:" << sum<<endl;
	return 0;
}
void fGraph()
{
	int min;
	for (int j = N - 1; j > 0; j--)//向前处理方法
	{
		min = INF;
		//for (int i = 1; i < N; i++)
		for (int i = j - 1; i > 0; i--)//从j - 1开始可以减少比较次数
		{
			if (c[i][j] != INF && cost[j] + c[i][j] < min)//找出结点r, 满足<j, r>∈E且使c(j,r)+COST(r)值最小
			{
				min = cost[i] + c[i][j];
				d[j] = i;
			}
		}
		cost[j] = min;//数组cost[i]保留到结点i的最短边的权值
	}
}
void init()
{
	for (int i = 1; i < N; i++)
	{
		cost[i] = 0;
		for (int j = 1; j < N; j++)
		{
			c[i][j] = INF;
		}
	}
	//为了测试方便,直接码出来了
	c[1][2] = 9; c[1][3] = 7; c[1][4] = 3; c[1][5] = 2;
	c[2][6] = 4; c[2][7] = 2; c[2][8] = 1; c[3][6] = 2;
	c[3][7] = 7; c[4][8] = 11; c[5][7] = 11; c[5][8] = 8;
	c[6][9] = 6; c[6][10] = 5; c[7][9] = 4; c[7][10] = 3;
	c[8][10] = 5; c[8][11] = 6; c[9][12] = 4; c[10][12] = 2;
	c[11][12] = 5;
	/*以下为获取数据方法
	cout << "请输入多段图结点的个数:" << endl;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			c[i][j] = INF;
		}
	}
	cout << "请输入多段图的段数:" << endl;
	cin >> k;
	cout << "请输入边的数量:" << endl;
	cin >> m;
	cout << "请依次输入各边的起点、重点及权值:" << endl;
	int x, y, z;
	for (int i = 0; i < m; i++)
	{
		cin >> x >> y >> z;
		c[x][y] = z;
	}
	*/

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liumce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值