陣列分割——解題筆記

bigface1234fdfg發表於2015-02-04

陣列分割——解題筆記

    

    題目:有一個沒有排序、元素個數為2n的正整數陣列,要求:如何能把這個陣列分割為元素個數為n的兩個陣列,並使兩個子陣列的和最接近。


    分析:這道題目可以用動態規劃求解,或者說是一個典型的0,1揹包問題,對於第i的數,到底是放進去還是不放,就要看放了對結果有什麼影響,不放對結果又有什麼影響。而結果是依據題目而言的,這道題目中的結果就是陣列之和。

    注意,一般動態規劃陣列中,需要先初始化所有i的結果,初始化可以為1,或者0. 然後,從前往後,依次得到每個i的優化結果,而且需要注意的是,第i個的結果只和第i-1個的結果有關

    在這道題目中,我參考了參考中的一篇博文,感覺講的比較清楚,如下:



給出的虛擬碼為:

F[][][]← 0

for i ← 1 to 2*N

    nLimit ← min(i,N)

    do for j ← 1 to nLimit

        do for k ← 1 to Sum/2

            F[i][j][k] ← F[i-1][j][k]

            if (k >= A[i] && F[i][j][k] < F[i-1][j-1][k-A[i]]+A[i])

                then F[i][j][k] ← F[i-1][j-1][k-A[i]]+A[i]

return F[2N][N][Sum/2]


    核心函式如下:


int splitArray(int a[], int len, int sum)
{
	int*** X; 
	X = new int**[len+1]; 
	for(int p = 0; p < len/2+1; p++)
	{
		X[p] = new int*[len/2+1]; 
		for(int q= 0; q < sum+1; q++)
			X[p][q] = new int[sum+1]; 
	}

	for(int i = 1; i <= len; i++)
	{
		int lim = min(i, len/2); 
		for(int j = 1; j <= lim; j++)
		{
			for(int k = 1; k <= sum; k++)
			{
				X[i][j][k] = X[i-1][j][k]; 
				if(k >= a[i-1])
				{
					if(X[i][j][k] < X[i-1][j-1][k-a[i-1]] + a[i-1])
					{
						X[i][j][k] = X[i-1][j-1][k-a[i-1]] + a[i-1]; 
					}
				}
			}
		}
	}

	int result = X[len][len/2][sum]; 
	//delete [][][]X; // 銷燬空間這種做法是錯誤的,應該和申請空間方法一樣
	return result; 
}


注意:其中申請三維動態空間的方法,以及銷燬的方法。


    上面解法的空間複雜度為O(N^2Sum),而且用到的是三維空間,是可以進行優化的。

我們觀察前面不含路徑的虛擬碼可以看出,F[i][j][k]只與F[i-1][][]有關,這一點狀態方程上也能反映出來。所以我們可以用二維陣列來代替三維陣列來達到降低空間複雜度的目的。但是怎麼代替裡面存有玄機,我們因為F[i][j][k]只與F[i-1][][]有關,所以我們用二維陣列來代替的時候應該對F[i][j][k]的“j”維進行逆序遍歷。為什麼?因為只有這樣才能保證計算F[i][j][k]時利用的F[i-1][j][]和F[i-1][j-1][]是真正i-1這個狀態的值,如果正序遍歷,那麼當計算F[][j][]時,F[][j-1][]已經變化,那麼計算的結果就是錯誤的。
虛擬碼如下
[cpp] view plaincopy
F[][]← 0

for i ← 1 to 2*N

nLimit ← min(i,N)

do for j ← nLimit to 1

do for k ← A[i] to Sum/2

if (F[j][k] < F[j-1][k-A[i]]+A[i])

then F[j][k] ← F[j-1][k-A[i]]+A[i]



return F[N][Sum/2] and Path[][][]



    動態規劃的題目寫起來還是不順額。。。


參考:

http://blog.csdn.net/wumuzi520/article/details/7028705

http://wenku.baidu.com/link?url=CQkQIsOqAYP41MuP9yavgklpHiST6BXXDi2zwfvGnRZEDHMF6S7LrwinwMPW3C6YAKkBw2i397aLNtppediKQ2nPJ4BSqFo8KUb0VbmA1Eu


相關文章