(1)問題の説明:問題のサブセットと、例えば<データ、NUM>。{式中、X =データ。1、X 2、...、X n-は }正の整数の集合であり、targetValueは正の整数です。データのそこDATA1サブセット場合サブセット和問題の決定は、そのようなことを
X 1 + X 2 + ... + X N = targetValue(X€DATA1)
(2)アルゴリズムを設計:バックトラッキングアルゴリズムは、所与のセットのために、ツリーのサブセットを解決するために使用される{X =データ。1、X 2、...、X N- } targetValueとデータDATA1のサブセット計算正の整数、 [X満たす。1 + X 2 + ... + X N- = targetValue(X€DATAL)]
(3)アルゴリズムコード:
パブリック クラスSubsetSum { / ** *目標 * / プライベート 静的整数targetValue; / ** *現在選択されている要素の和 * / プライベート 静的整数SUM = 0 ; / ** *データの数 * / プライベート 静的NUM整数。 / ** *未定着値 * / プライベート 静的整数indeterminacyValue = 0 ; / * *データアレイ * / プライベート 静的整数[]データ; / ** *データストレージ[0:1ストレージ:ストア] * / プライベート 静的整数[]ストア; / ** *初期化データ * / プライベート 静的 無効initData(){ スキャナ入力 = 新しい新しいスキャナ(System.in); System.out.printlnは( "ターゲットを入力してください:" ); targetValue = INPUT。 nextInt(); System.out.printlnは( "データの番号を入力してください:" ); NUM = input.nextInt(); データ = 新新[NUM]整数; ストア = 新しい新しい[NUM]整数; System.out.printlnは(「それぞれの番号を入力してください:」); のため(のInt I = 0; I <data.length; I ++ ){ DATA [I] = input.nextInt(); ストア[I] = 0; // 初期化が格納されていない indeterminacyValue + = データ[I]; } } / ** *バック見つける * / プライベート 静的ブール後戻り(int型I){ IF(SUM == targetValue){ // 直接戻るtrueに、実現可能な解決策を見つける リターン trueに; } のIF(data.length == I){ // 取得少ない実現可能な解決策よりも、直接のリターン偽 リターン 偽; } IndeterminacyValue - =データは、[I]は; // 数の合計が決定されていない計算 IF(和+データ[I] <= targetValue ){ // 現在の和+データ[I] <= targetValue 直接に左サブツリー ストア[I] = 1; // 選択された加算値に含まれるiが格納されたデータ、 SUM + = データ[I]; IF(バックトラック(I + 1)){ // 継続加算層深さ決意 リターン trueにします; } 合計 - =データ[I]; // 完成深さを解決するため、溶液が満たされていない必要に応じて、現在の開始値和を復元するために必要性を戻っ } IF(+ indeterminacyValue SUM> = targetValue){ // プルーニング関数[+未定値現在の和> =目標値であれば、右サブツリー検索深度に入る前に、そうでなければ、何の意味] ストア[I] = 0; // 私はこの場合、データは選択された加数に含まれ、格納されていない IF(バックトラック(I + 1 )){ リターン trueに; } } indeterminacyValue ; + =データ[I]は // の条件下で満足ならば、完成し深さを解決します解決策は、現在の開始値indeterminacyValueの復元するために、バックトラックを必要と リターン falseにする; } / ** *出力 * / プライベート 静的 無効印刷(){ System.out.printlnは(「\ n型データ配列:」); Stream.of(データ).forEach(素子 - > System.out.print(エレメント+ "" )); System.out.println(); System.out.println( "数据存放:" ); Stream.of(店舗).forEach(素子 - > System.out.print(エレメント+ "" )); System.out.println(); System.out.println( "组成该目标值的数为:" ); 以下のために(INT ; I <store.length; iが0 = I ++ ){ 場合(ストア[I] == 1 ){ System.out.print(データ[I] + "" )。 } } システム。 静的 ボイドメイン(文字列[]引数){ // 初期化データ initData(); // バック見つけるために バックトラックを(0 ); // 出力 プリント(); } }
(4)入力と出力:
ターゲットを入力してください 10は、 データの番号を入力: 5は :それぞれの数値入力 22654 データ配列: 22654 データストレージ: 11100 ターゲット組成の数である: 226
(5)まとめ:サブセットとも完全にツリーをバックトラックサブセットのコア思想、O(2の時間複雑さを反映N-をストレージソリューションによって、)と存在しない場合は、一度、かプルーン、侵入深さ検索を決定しますへの即時復帰への解決策を検索します。
推奨事項:私は紙で絵を描く、私のコードの考えによると、肉眼を理解していない場合は再度、簡単にコードを理解するために、プロセスを解決歩く、セットツリーをバックトラックの核となるアイデアをマスターするための別の方法。