MyException - 我的异常网
当前位置:我的异常网» 编程 » 数组瓜分——解题笔记

数组瓜分——解题笔记

www.MyException.Cn  网友分享于:2015-02-11  浏览:0次
数组分割——解题笔记

数组分割——解题笔记

    

    题目:有一个没有排序、元素个数为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


文章评论

程序员应该关注的一些事儿
程序员应该关注的一些事儿
我是如何打败拖延症的
我是如何打败拖延症的
60个伟德国际app者不容错过的免费资源库
60个伟德国际app者不容错过的免费资源库
我的丈夫是个程序员
我的丈夫是个程序员
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
程序员都该阅读的书
程序员都该阅读的书
Web伟德国际app者需具备的8个好习惯
Web伟德国际app者需具备的8个好习惯
中美印日四国程序员比较
中美印日四国程序员比较
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
10个调试和排错的小建议
10个调试和排错的小建议
Java程序员必看电影
Java程序员必看电影
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
编程语言是女人
编程语言是女人
 程序员的样子
程序员的样子
程序员的鄙视链
程序员的鄙视链
旅行,写作,编程
旅行,写作,编程
那些争议最大的编程观点
那些争议最大的编程观点
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
如何成为一名黑客
如何成为一名黑客
漫画:程序员的工作
漫画:程序员的工作
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
程序员必看的十大电影
程序员必看的十大电影
每天工作4小时的程序员
每天工作4小时的程序员
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
2013年美国伟德国际app者薪资调查报告
2013年美国伟德国际app者薪资调查报告
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
2013年中国软件伟德国际app者薪资调查报告
2013年中国软件伟德国际app者薪资调查报告
为什么程序员都是夜猫子
为什么程序员都是夜猫子
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
代码女神横空出世
代码女神横空出世
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
一个程序员的时间管理
一个程序员的时间管理
总结2014中国互联网十大段子
总结2014中国互联网十大段子
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
Web伟德国际app人员为什么越来越懒了?
Web伟德国际app人员为什么越来越懒了?
软件伟德国际app程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有