问题:
第一行是一个数字n
接下来m个数字在数组a中
要求输出对应下标使去掉这些数字时剩下的数字之和为n
例如:
6
3 2 4 3 1
此时,程序输出:
0 2
0 3 4
1 2 4
2 3
代码如下:
public class Main{
//err_sum:有错的和
//a:明细
//k:当前处理的位置
//cur_sum :当前的和
//b:记录取舍
public static void g(int err_sum, int[] a, int k, int cur_sum, boolean[] b) {
if (cur_sum > err_sum) return ;
if (err_sum == cur_sum) {
for (int i=0; i<b.length; i++)
if(b[i]==false) System.out.print(i+" ");
System.out.println();
return;
}
if (k>=a.length) return ;
b[k] = false;
g(err_sum, a, k+1, cur_sum, b);
b[k] = true;
cur_sum += a[k];
g(err_sum, a, k+1, cur_sum, b);
b[k] = false;// 回溯!!!
}
public static void main(String[] args) {
int sum = 6;
int[] a = {3,2,4,3,1};
boolean[] b = new boolean[a.length]; //表示a的对应项是否选取
g(6, a, 0, 0, b);
}
}
思路:b数组指出a数组哪些数应该被输出,是一个标志数组。我们递归结束有三个条件,如果当前错误大于总错误,直接return;如果当前错误等于总错误,说明这种符合要求,要将此时b数组对应的a数组下标输出。如果k移动到了数组最后一个位置甚至大于,那么也要return,注意这里的次序不能颠倒。
当对a数组的元素依次计算时,每一个元素有两种情况,如果把这个元素加入到cur_sum中,那么要cur_sum+=a[k],否则不需要,而这两种情况都是要考虑的,因此先让b[k] = false,表示不加,进行递归,再让 b[k] = true,表示加。最后十分重要的一点是不要忘了程序的回溯:b[k] = false,因为b数组默认是不取的。