动态规划的一个简单实例java

如果一个问题可以分为多个子问题,这若干个子问题如果是相互独立的,那么我们可以使用分治的思想解决,如果分解的子问题之间并不是独立的,那么就可以使用动态规划来解决了。

动态规划原理:

一个最优策略的决策过程中产生的子问题的子策略必然也是最优的,简单的一个说明就是,最终的策略最优,必然是在前一个最优策略的基础上做出的最优策略。

动态规划的一般步骤:

1)描述最优解的结构

2)对最优解的值进行递归定义

3)按照自底向上的方法计算最优解的值

4)根据3)计算出的结果构造一个最优解


一个例子:

有两条生产线1,2,标记为i,每个生产线有n道工序,标记为j,每条生产线上的第j道工序的功能相同,但是消耗的时间不同,当产品进入生产线之后,可以在任意一道工序j完成之后将产品转移到另一条生产线的第j+1道工序,转换线路会消耗时间Tij,表示在第i条生产线上完成了第j道工序之后转移到另一条生产线所消耗的时间。ei表示进入第i条生产线所消耗的时间,xi表示从第i条生产线离开时消耗的时间。画图表示为:

《动态规划的一个简单实例java》


其中:

entraA是进入第1条生产线消耗的时间

entraB是进入第2条生产线消耗的时间

aij表示第i条生产线的第j道工序消耗的时间

tij表示从第i条生产线的第j道工序转移到另一条生产线的第k+1道工序过程中消耗的时间

exitA表示离开第1条生产线消耗的时间

exitB表示离开第2条生产线消耗的时间


分析:

1 如果j=1,那么只有一条路径,我们可以比较entraA和entraB的大小即可,如果j>=2,有两种可能,一是产品直接从同一条生产线的前一道工序过来,进入了第j道工序,二是产品是从另一条生产线转移过来,这个过程花费了tij-1的时间。但是已经确定的是从产品进入生产线 一直到出了第j-1道工序必定是最快的路径。这是我们递推的假设,我们就这样分析出了子问题,即,要求第j道工序的最快路径,我们可以先求第j-1道工序的最快路径。

2 定义表达式  

fi[j]表示一个产品从起点进入生产线一直到第i条生产线的第j道工序的最快时间

f*表示全程的最快路径,问题可以表示为如下方程:

f* = min(f1[n]+exitA,f2[n]+exitB)

n为总共的工序

初始化条件为:

f1[1]=entraA+a1,1                                                                                      (1)

f2[1]=entraB+a2,1                                                                                      (2)

当j>=2时,我们就需要考虑1中分析的两种情况了

f1[j]=min(f1[j-1]+a1,j,f2[j-1]+t2,j-1+a1,j)                                      (3) 

f2[j]=min(f2[j-1]+a2,j,f1[j-1]+t1,j-1+a2,j)                                         (4)


java实现:

	/**
	 * @param a 每道工序消耗的时间
	 * @param t 转移到另一条生产性消耗的时间
	 * @param line 用于记录最优线路
	 * @param entraA 进入生产线1的时间
	 * @param entraB 进入生产线2的时间
	 * @param exitA 离开生产线1消耗的时间
	 * @param exitB 离开生产线2消耗的时间
	 * @param n 工序的总数
	 */
	public static void fastWayTime(int[][] a, int[][] t, int[][] line, int entraA, int entraB, int exitA, int exitB, int n) {
		int minTime;
		int[][] f = new int[2][3];
		f[0][0] = entraA + a[0][0];   //(1)的表示 初始化
		f[1][0] = entraB + a[1][0];   //(2)的表示
		for(int j = 1;j<n;j++) {
			if(f[0][j-1] + a[0][j] <= f[1][j-1] + t[1][j-1] + a[0][j]) {   //(3)
				f[0][j] = f[0][j-1] + a[0][j];
				line[0][j] = 0;  			//line的第0位不记录生产线,因为它只能从起点进入第一道工序
			} else {
				f[0][j] = f[1][j-1]+t[1][j-1]+a[0][j];
				line[0][j] = 1;				//line的第0位不记录生产线,因为它只能从起点进入第一道工序
				
			}
			if(f[1][j-1] + a[1][j] <=f[0][j-1]+t[0][j-1]+a[1][j]) {       //(4)
				f[1][j] = f[1][j-1] + a[1][j];
				line[1][j] = 1;				//line的第0位不记录生产线,因为它只能从起点进入第一道工序
			} else {
				f[1][j] = f[0][j-1] +t[0][j-1] +a[1][j];
				line[1][j] = 0;				//line的第0位不记录生产线,因为它只能从起点进入第一道工序
			}
			
		}
		if(f[0][n-1]+exitA <= f[1][n-1] +exitB) { //f数组中记录了各条线路的各道工序的最短时间,因此只需要比较最后一道工序就行了
			minTime = f[0][n-1] + exitA;
		} else {
			minTime = f[1][n-1] + exitB;
		}
		System.out.println("最快路径耗时: "+minTime);
		fastWayPath(line, lastStation, n);
	}
	
	public static void fastWayPath(int[][] line, int lastStation, int n) {
		int i = lastStation;
		Stack<Integer> path = new Stack<Integer>();
		path.push(i);
		for(int j=n;j>1;j--) {
			i = line[i][j-1];  //line记录的是第j道工序的最优解的前一道工序是从哪条线路过来的,因此必须从后往前读取
			path.push(i);
		}
		int k=1;
		while(!path.isEmpty()&& k<=n) {
			System.out.println("线路"+(path.pop()+1)+": 工序"+k);
			k++;
		}
	}

	public static void main(String[] args) {
		int[][] a = {{4,3,2},{2,2,3}};
		int entraA = 2;
		int entraB = 1;
		int exitA = 2;
		int exitB = 3;
		int[][] t = {{4,1},{3,2}};
		int n = 3;
		int[][] line = new int[2][3];
		fastWayTime(a, t, line, entraA, entraB, exitA, exitB, n);

	}

    原文作者:动态规划
    原文地址: https://blog.csdn.net/ghl_kevin/article/details/72830658
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞