论坛首页 编程语言技术论坛

关于背包算法由递归转迭代实现

浏览 1947 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-01-26  

背包算法应用很广泛,也是经典算法了,最近由于项目需要,使用了此算法。

查找到以下博客: http://puffsun.iteye.com/blog/1286331

这个写的简单易懂,估计大家一看就明白了,使用了递归算法,开始余量等于总数,容易每次循环,进行操作,直到余量等于0为止,但是还有个小Bug,打印的时候,中间有大于的时候需要跳过的,当然,他只求是否有解,我是需要答案,也不算是Bug吧。

原算法如下:

     * @author Sun Kui  
     */  
    public class Knapsack {  
        public static void main(final String... args) {  
            int[] arr = new int[5];  
            arr[0] = 11;  
            arr[1] = 8;  
            arr[2] = 7;  
            arr[3] = 5;  
            arr[4] = 3;  
            Knapsack k = new Knapsack();  
            System.out.println(k.knapsack(arr, 0, 20, 20));  
        }  
      
        /** 
         *@param arr    all of items in knapsack 
         *@param start  the start item to be put into the knapsack 
         *@param left   the remaining capacity of knapsack 
         *@param sum    capacity of knapsack 
         */  
        public boolean knapsack(int[] arr, int start, int left, int sum) {  
      
            if (arr.length == 0) {  
                return false;  
            }  
      
            // start from the next item in original array  
            if (start == arr.length) {  
                int[] tempArr = new int[arr.length - 1];  
                for (int i = 0; i < tempArr.length; i++) {  
                    tempArr[i] = arr[i + 1];  
                }  
                return knapsack(tempArr, 0, sum, sum);  
            } else if (arr[start] > left) {  
                return knapsack(arr, start + 1, left, sum);  
            } else if (arr[start] == left) {  
                for (int i = 0; i < start + 1; i++) {  
                    // print the answer out  
                    System.out.print(arr[i] + "\t");  
                }  
                System.out.println();  
                return true;  
            } else {  
                return knapsack(arr, start + 1, left - arr[start], sum);  
            }  
        }  
    }  

 

 

我修改后如下, 

 

public class Knapsack {
	public static void main(final String... args) {
//		int a=5000;
//		int[] arr = new int[a];
//		for(int i=0;i<a;i++){
//			arr[i]=1;
//		}
//		Knapsack k = new Knapsack();
//		k.knapsack(arr, 0, a, a);
		//System.out.println(k.knapsack(arr, 0, a, a));
		
		int[] arr = new int[5];
		arr[0]=11;
		arr[1]=5;
		arr[2]=5;
		arr[3]=3;
		arr[4]=1;
		Knapsack k = new Knapsack();
		k.knapsack(arr, 0, 20, 20);
		System.out.println(k.knapsack(arr, 0, 20, 20));
	}

	/**
	 * @param arr
	 *            all of items in knapsack
	 * @param start
	 *            the start item to be put into the knapsack
	 * @param left
	 *            the remaining capacity of knapsack
	 * @param sum
	 *            capacity of knapsack
	 */
	public boolean knapsack(int[] arr, int start, int left, int sum) {
		if(start%500==0){
			System.gc();
		}
		if (arr.length == 0) {
			return false;
		}

		// start from the next item in original array
		if (start == arr.length) {
			int[] tempArr = new int[arr.length - 1];
			for (int i = 0; i < tempArr.length; i++) {
				tempArr[i] = arr[i + 1];
			}
			return knapsack(tempArr, 0, sum, sum);
		} else if (arr[start] > left) {
			arr[start]=0;
			return knapsack(arr, start + 1, left, sum);
		} else if (arr[start] == left) {
			for (int i = 0; i < start + 1; i++) {
				// print the answer out
				System.out.print(arr[i] + "\t");
			}
			System.out.println();
			return true;
		} else {
			return knapsack(arr, start + 1, left - arr[start], sum);
		}
	}
}

 

请查看注释,如果我有超过5千的数据量需要使用此算法,则会抛出异常:StackOverflowError

当然,网上有调用gc的,有调JVM内存大小的,但这都不能解决问题,无意中,我看到一句话:

所有递归都是可以用迭代实现的

 

我就感觉有救了,今天被这个事情折腾的,数据都做不下去了,谢谢这位仁兄,我用迭代实现了如下,不知道有没有Bug,不过没时间测试了,先搞上去吧,2单数据已经无法做了。

 

import java.util.ArrayList;
/**
 * @author  xy792
 */
public class CopyOfKnapsack {
	public static void main(final String... args) {
		int a = 100000;
		int[] arr = new int[a];
		for (int i = 0; i < a; i++) {
			arr[i] = 1;
		}
		
		
//		int[] arr = new int[5];
//		arr[0]=11;
//		arr[1]=5;
//		arr[2]=5;
//		arr[3]=3;
//		arr[4]=1;
		
		CopyOfKnapsack k = new CopyOfKnapsack();
		 
		System.out.println(k.knapsack(arr, 0, a, a).size());
	}

	/**
	 * @param arr
	 *            all of items in knapsack
	 * @param start
	 *            the start item to be put into the knapsack
	 * @param left
	 *            the remaining capacity of knapsack
	 * @param sum
	 *            capacity of knapsack
	 */
	public ArrayList<Integer> knapsack(int[] arr, int start, int left, int sum) {
		ArrayList<Integer> list = new ArrayList<Integer>();
		if (arr.length == 0) {
			return list;
		}
		int end = arr.length + 1;
		int temp = 0;
		while (start < end) {
			if (start == arr.length) {
				start = ++temp;
				int[] tempArr = new int[arr.length - 1];
				for (int i = 0; i < tempArr.length; i++) {
					tempArr[i] = arr[i + 1];
				}
				arr = tempArr;
				end--;
				continue;
			}
			if (arr[start] > left) {
				arr[start] = 0;
				start++;
			} else if (arr[start] == left) {
				for (int i = 0; i < start + 1; i++) {
					//System.out.print(arr[i] + "\t");
					if (arr[i] != 0) {
						list.add(arr[i]);
					}
				}
				return list;
			} else {
				left = left - arr[start];
				start++;
			}

		}
		return list;
	}
}

 

如有建议,或者Bug,可以留言。

end

      

 

论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics