算法详解(四):动态规划-装载问题

参考完往上面的动态规划解决装载问题,总是觉得少了点什么,其实很多他们算不上真正的动态规划,他们只是对于决策不断求解,并没有选出最优的答案,接下来,我就把我对于动态规划的理解,解决出装载的问题(算法中没有选出船的具体装载箱子)

一:问题描述

  • 两艘船各自可装载重量为c1,c2,n个集装箱,各自的重量为w[n],设计一个可以装载的方案,使得两艘船装下全部集装箱

二:算法概念

  • 阶段
    • 将所给问题的过程,恰当的分为若干相互联系的阶段,以便能按一定的次序求解问题。阶段的划分一般是根据时间和空间的特征进行的,但是要能够把问题的过程转化为多阶段决策问题。
  • 状态
    • 状态表示每个阶段开始所处的自然状况或者客观条件
  • 决策
    • 决策表示当过程处于某一阶段某一状态时,可以做出的决定,从而确定下一阶段的状态

二:程序流程

  • 将第一艘船尽量装满(第一艘船放的集装箱的重量之和接近c1),剩余的集装箱放入第二艘船,若剩余的集装箱重量之和大于第二艘船,则无解

  • 定义一个一维数组,a[n] 存放对应的集装箱的重量

  • 定义一个数组,m[i][j]表示第一艘船还可装载的重量j,可取集装箱编号范围为i,i+1…n的最大装载重量值
    例如 现在有3个集装箱 重量分别为9,5,3,即a[1]=9 a[2]=5 a[3]=3

    • m[1][2]=0 可装载重量为2,此时上述的三个集装箱都不能装入,所以为最大可装载重量为0
    • m[1][3]=m[1][4]=3 可装载重量为3或者是4的时候,都是只能装入重量为3的那个集装箱,所以最大可装载重量为3 实际上,这里的3=a[3]+m[1][2],是一个递推的关系,具体看下面
  • m[i][j]分下面两种情况

    • 0<=j<a[n] (当可装载重量j小于第n个集装箱的重量w[n],此时就不能往船上装此集装箱) m[i][j] = m[i+1][j]
    • j>=a[n] (可装载重量j大于或等于第n个集装箱的重量w[n]),此时剩余的可装载重量为j-an,最大的可装载重量为m[i+1][j-w[n]]+w[n]
      但是我们是需要最大的可装载重量,所以得与如果不将当前集装箱装入的那种情况m[i+1][j]进行比较
      m[i][j]=Math.max(m[i+1][j],m[i+1][j-a[n]+a[n]])
  • 上面我们就获得了一个关于m[i][j]的递推关系,我们通过逆推获得全部的数值

三:整体分析

  • 其实选择的最优化解的过程其实主要是对于选择船在某一个限定的容量下,所能够装载的最大容量,在这一阶段需要和前一阶段的行为进行比较,判断,该种装载是否最优,通过这样的一个步骤,就能够获取到最优的决策。
  • 主要是对于不停的根据下一层的结果来计算出上一层的最佳结果
for (int i1 = num - 1; i1 >= 1 ; i1--) {
		for (int j = 1; j <= C1 ; j++ ) {
			if ( w[i1] > j ) {
				m[i1][j] = m[i1+1][j];
				x[i1] = false;
			} else {
				int temW = w[i1] + m[i1+1][ j - w[i1] ];
				if ( temW > m[i1+1][j]  ) {
					m[i1][j] = temW ;
					x[i1] = true;			
				}else{
					m[i1][j] = m[i1+1][j]; 
					x[i1] = false;
				}			
			}
		}
	}

四:代码呈现

#include <stdio.h>
#include <stdlib.h>
 

 
void Loading(int C1,int* w,int num,bool* x,int** m){
	for (int i = 1; i < C1+1 ; i++ ) {
		if ( w[num] > i ) {
			m[num][i] = 0;
			x[num] = false;
		} else {
			m[num][i] = w[num];
			x[num] = true;
		}
	}
 
	for (int i1 = num - 1; i1 >= 1 ; i1--) {
		for (int j = 1; j <= C1 ; j++ ) {
			if ( w[i1] > j ) {
				m[i1][j] = m[i1+1][j];
				x[i1] = false;
			} else {
				int temW = w[i1] + m[i1+1][ j - w[i1] ];
				if ( temW > m[i1+1][j]  ) {
					m[i1][j] = temW ;
					x[i1] = true;			
				}else{
					m[i1][j] = m[i1+1][j]; 
					x[i1] = false;
				}			
			}
		}
	}
	int max = m[1][1];
	for (int i = 1; i <= C1; i++){
		if(m[1][i]>max&&m[1][i]<=C1)
			max = m[1][i];
	} 
	int totalW = 0;
	for (int i = 1; i <= num ; i++ ) {
		totalW += w[i];
	}
	printf("第一艘船能够装载的最大重量:%d\n", max);
	printf("第一艘船能够装载的最大重量:%d\n", totalW - max);
}
 
int main(int argc,char* argv[]){
	
	int C1 = 0;
	int C2 = 0;
	int num = 0;
	bool* x = NULL;
	int** m = NULL;
	int* w = NULL;
 
	printf("输入第一艘船最大载重量:");
	scanf("%d",&C1);
 
	printf("输入第二艘船最大载重量:");
	scanf("%d",&C2);
 
 
	printf("输入货物个数:");
	scanf("%d",&num);
 
	x = (bool*)malloc((num+1)*sizeof(bool));
	w = (int*)malloc((num+1)*sizeof(int));
 
	m = (int**)malloc((num+1)*sizeof(int*));
	for (int i = 0; i <= num ; i++ ) {
		m[i] = (int*)malloc( (C1+1) * sizeof(int) );
	}
	printf("分别输入货物重量(回车结束):\n");
 
	for (int i = 1; i <= num ; i++ ) {
		scanf("%d",w+i);
	}
	
	for (int i = 1; i<=num;i++){
		m[i][0] = 0;
	}
 
	Loading(C1, w, num, x, m);
 
	return 0;
}

前面的算法而分析是参考了某客上面的分析

五:运行结果

在这里插入图片描述

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值