动态规划法求最优分配方案(空间优化)

问题:

    某厂根据计划安排,拟将n台相同的设备分配给m个车间,各车间获得这种设备后,可以为国家提供盈利Ci j(i台设备提供给j号车间将得到的利润,1≤i≤n,1≤j≤m) 。问如何分配,才使国家得到最大的盈利?

动态规划法:

算法思想:

    将m个车间划分为前m-1个和第m个,每次给第m个车间分配的时候都是建立在前m-1的最优策略的基础上(总利润最大),再进行最优分配。这样在迭代的过程中就能保证每一次都是最优的,从而到最后的整体最优。

最优值递推公式:

    maxProf[ i ] [ j ] = MAX( maxProf [ i -1 ] [ k ] + eachProf [ i ] [ j-k ] )

    其中maxProf [ i ] [ j ] = 0 ( i==0 || j==0 ),k的范围为0至j。

算法实现:

    该算法需要三个二维数组,三张表分别记录每个车间的初始盈利eachProfit,每种情况的最优总利润maxProfit,以及每种情况的分配方案distribution。初始盈利必须保证同一个车间,其盈利必定会随着设备数的增加而增加。

伪代码:

初始利润生成:
for i = 1 to m
	eachProfit[i][0] = 0				//0设备的情况下价值为0
	for  j = 1 to n
	//为每个车间分配设备的利润初始化,并保证同一车间设备增加利润也增加
		eachProfit[i][j] = eachProfit[i][j-1] + rand() % 10 + 3

最优方案生成:
for i = 1 to m
		for j = 1 to n
			for k = 0 to j 
				if  maxProfit[i][j] < maxProfit[i - 1][k] + eachProfit[i][j - k] 
					maxProfit[i][j] = maxProfit[i - 1][k] + eachProfit[i][j - k]
					distribution[i][j] = j - k

分配方案的输出:
k = n
	for i = m downto 1 
		cout << "(" << i << "," << distribution[i][k] << ")" << endl
		k =  k - distribution[i][k]

二表优化动态规划法:

算法思想:

   在一般的动态规划法求解过程中,eachProfit和maxProfit两张表并不是所有内容都时刻需要的,例如在求解最大利润时maxProfit[i][j] = maxProfit[i - 1][k] + eachProfit[i][j - k]时,当我们要求i个车间和j台设备的利润时,只需用到maxProfit的第i - 1行和eachProfit的第i行,前面计算过的内容已经无需再保存了,所以我们可以将两张二维表压缩成两个一维数组。

算法实现:

     二表优化的方法与原本的动态规划相比除了表格的大小,还有求解的顺序的不同。因为从最优值递推公式maxProfit[i][j] = maxProfit[i - 1][k] + eachProfit[i][j - k]可以看出,每次求i个车间j台设备的最优分配情况时,除了用到maxProfit的第i - 1行和eachProfit的第i行,还要用到maxProfit中小于或等于k,eachProfit中小于或等于j - k的列,其中k与j - k都小于j,所以要保证要用到的元素没有被改变过,在求解最大盈利的时候需要从设备总数最大的情况开始求解,如果从小的开始求解,在求解设备总数大的时候,其所用到小的最优情况已经被改变了,会导致结果出错。

伪代码:

每生成一行eachBetter求出一行maxBetter:
for  i = 0 to n
	maxBetter[i] = 0
for i = 1 to m
	eachBetter[0] = 0
	for j = 1 to n
		eachBetter[j] = eachBetter[j - 1] + rand() % 10 + 3
	betterDynamic(n, i)

求出每一行的最大盈利和记录分配方案:
void betterDynamic(int n, int i) 
	for j = n downto 1
		max = 0
		for k = j downto 0
			if  max < maxBetter[k] + eachBetter[j - k]
				max = maxBetter[k] + eachBetter[j - k]
				maxBetter[j] = max
				distribution[i][j] = j - k

   相比未优化的动态规划,二表优化主要体现在空间上的优化,原本需要的内存空间至少为3mn个int,改进后为mn+2n个int(在规模为数万的情况下,用int比较合理,因为unsigedshort的最大值为6万多,而初始盈利必须保证同一个车间,其盈利会随着设备数的增加而增加,这就表示用短整型会出现大量重复的数据,不同车间之间的比较意义就不太大了)。

   另一个重要的点是按行求解最大盈利和按列求解所花费的时间会有不同。因为二维数组在内存中的储存方式是按顺序一行行存的,在求解时按行求解也符合储存方式,时间效率会比较高。

你可能感兴趣的:(算法设计与分析)