子集和數問題


[問題描述]

已知n個正數:wi, 1<=i<=n, 和M。要求找出{wi }的所有子集使得子集內元素之和等於M。例如:

    n=4,     (w1,w2,w3,w4)=(11,13,24,7),M=31

   則滿足要求的子集是(11,13,7)和(24,7)。

/*子集和數問題:已知n個正數:wi, 1<=i<=n, 和M。
    要求找出{wi }的所有子集使得子集內元素之和等於M。例如:
	n=4, (w1,w2,w3,w4)=(11,13,24,7),M=31
則滿足要求的子集是(11,13,7)和(24,7)。

思路:
子集和數問題解的一種表示方法
解由n-元組(x1, x2, …, xn)表示;
顯式約束條件xi∈{0,1} ,1≤i≤n,如果沒有選擇Wi,則xi=0;
		如果選擇了Wi,則xi=1。於是上面的解可以表示為(1,1,0,1)和(0,0,1,1);
隱式約束條件(xi× wi)的和數為M
*/

public class sonNum {
	
	//定義一個數組表示集合
	static int[] num = {11,13,24,7};
	//sum用來做加法,比較判斷是否等於m
	static int sum = 0;
	//用來表示最終的解{0,1,1,1}形式
	static int[] result = new int[num.length];
	//給定的m
	static int m = 31;	
	
	//回溯方法
	static public void backTrack(int count){
			//如果count等於集合的長度則代表已經運行結束
			if(count == result.length){
				return;
			}
			
			else{
				//1的情況代表選擇將該數加進sum里,0的情況就是不要這個數
				for (int i = 0; i <= 1 ; i++) {
					sum += i*num[count];
					//result用來記錄是否選擇該數 選擇則置1,不選擇則置0
					result[count] = i ;
					
					//如果運行到sum等於m的時候,則代表找到了一組解
					//將這組解打印輸出
					if(sum == m){
						for (int j = 0; j < result.length; j++) {
							//判斷當前數的狀態是否為選中狀態 是則將該數打印出來
							if(result[j] == 1){
								System.out.print(num[j]+"\t");
							}
						}
						System.out.println();
					}
					
					//如果當前sum小於m,則進行下一個數的判斷
					if(sum < m){
						backTrack(count+1);
					}
					
					//回溯
					sum -= i*num[count];
				}
			}
	}
	
	public static void main(String[] args) {
		backTrack(0);
	}
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM