5-1 子集和问题
问题描述
子集和问题的一个实例为⟨S,t⟩〈S,t〉。其中,S={x1,x2,...,xn}S={x1,x2,...,xn}是一个正整数的集合,c是一个正整数。子集和问题判定是否存在 S 的一个子集 S1,使得 ∑x∈S1x=c∑x∈S1x=c。
试设计一个解子集和问题的回溯法。
对于给定的正整数的集合 S={x1,x2,...,xn}S={x1,x2,...,xn}和正整数 c,编程计算 S 的一个子集S1,使得∑x∈S1x=c∑x∈S1x=c。
数据输入:
第 1 行有 2 个正整数 n 和 c,n 表示 S 的大小,c是子集和的目标值。接下来的 1 行中,有 n 个正整数,表示集合 S 中的元素。
Java
package Chapter5HuiSuFa;
import java.util.Scanner;
public class ZiJiHe {
private static int n,c,cw,r,bestw;
private static int[] w,x,bestx;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
while (true){
cw = 0;
r = 0;
bestw = 0;
n = input.nextInt();
c = input.nextInt();
w = new int[n+1];
x = new int[n+1];
bestx = new int[n+1];
for(int i=1; i<=n; i++){
w[i] = input.nextInt();
r += w[i];
}
if(backtrack(1))
for(int i=1; i<=n; i++){
if(bestx[i] == 1)
System.out.print(w[i]+" ");
}
else
System.out.println("No Solution!");
}
}
private static boolean backtrack(int i){
if(i > n){
for(int j=1; j<=n; j++)
bestx[j] = x[j];
bestw = cw;
if(bestw == c)
return true;
else
return false;
}
r -= w[i];
if(cw+w[i] <= c){
x[i] = 1;
cw += w[i];
if(backtrack(i+1))
return true;
cw -= w[i];
}
if(cw+r > bestw){
x[i] = 0;
if(backtrack(i+1))
return true;
}
r += w[i];
return false;
}
}
Input & Output
5 10
2 2 6 5 4
2 2 6
Reference
王晓东《计算机算法设计与分析》(第3版)P179

本文探讨了如何利用回溯法解决子集和问题。给定一个包含正整数的集合S和目标和c,目标是找出S的一个子集,其元素之和等于c。文章提供了问题描述,并给出了基于Java的解决方案,包括数据输入和输出的说明。
1897

被折叠的 条评论
为什么被折叠?



