/*
* 注意:题目中说明有问题,应该是第2,3,7,14个数的组合和 第2,3,8,14个数的组合
* 看起来是一样的,都是{3,4,5,17},那么只视为一种。
* 但是:第1,4,6,10,11个数的组合{1,2,7,10,9}和第1,4,11,12,13个数的组合
* {1,2,9,10,7}并不是同一种,如果对输入的序列进行了排序,那么这两个组合会
* 变成同一个组合{1,2,7,9,10},所以不能对输入的序列先排序后处理。 */
/* 本算法不适用于包含负数的情况 */
/*
* 另1:如果得到答案是96,说明对原始序列进行了排序
* 另2:如果得到答案是52,说明不但对原始序列进行了排序,还进行了去重操作。这
* 是错误的,因为组合可能包含多个相同的数字,去重后把这部分组合丢掉了。
* 另3:如果得到答案是223,说明没有排除组合完全一致的情况(例如第2,3,7,14个数的组合和
* 第2,3,8,14个数的组合)
* 另4:如果得到答案是2,说明你求的是满足条件的子序列(下标连续,如{4,2,6,7,5,5}
* 或{10,9,10})的个数
* 另5:如果得到答案是152,说明求的是满足条件:“构成组合的数字不能重复”的组合个数
*/
#include "stdafx.h"
#include<iostream>
#include<vector>
#include<set>
using namespace std;
void SubSet(vector<int>& arr, set<vector<int>>& set, vector<int>& tmp, int index, int sum)
{
//越界返回
if (index == arr.size()) return;
//边界条件不满足返回
if (sum < 0) return;
//找到满足条件的子集
if (arr[index] == sum)
{
//纪录子集的最后一个元素
tmp.push_back(arr[index]);
//将子集的副本保存
set.insert(tmp);
//删除最后一个加入的元素
tmp.pop_back();
//如果不选取index对应的数字时,求能得到的满足条件的子集
SubSet(arr, set, tmp, index + 1, sum);
return;
}
/******** arr[index] <> sum的情况 *********/
tmp.push_back(arr[index]);
//选取当前元素的方案:
SubSet(arr, set, tmp, index + 1, sum - arr[index]);
tmp.pop_back();
//不选取当前元素的方案:
SubSet(arr, set, tmp, index + 1, sum);
}
int _tmain(int argc, _TCHAR* argv[])
{
int Num/*序列大小*/, SUM/*子集和*/;
cin >> Num >> SUM;
//序列
vector<int> Arr(Num, 0);
for (unsigned i = 0; i < Num; i++)
{
cin >> Arr[i];
}
//临时存放子集
vector<int> Tmp;
//存放所有子集
set<vector<int>> sets;
//求解所有子集
SubSet(Arr, sets, Tmp, 0, SUM);
//子集个数---136
cout << sets.size() << endl;
//子集详情
for (auto a : sets)
{
for (auto b : a)
cout << b << " ";
cout << endl;
}
return 0;
}
import java.util.*;
public class HelloWorld{
static int num=0;
static int a[]={1, 3, 4, 2, 6,7,5,5,8,10,9,10,7,17};
static ArrayList list=new ArrayList();
static TreeSet set=new TreeSet();
public static void main(String []args){
digui(0,29);
System.out.println(set.size());
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
}
}
public static void digui(int ge,int sum){
if(ge>=a.length||sum<=0){
if(sum==0){
set.add(list.toString());
}
return;
}
list.add(a[ge]);
digui(ge+1,sum-a[ge]);
list.remove((Integer)a[ge]);
digui(ge+1,sum);
}
}
为什么答案是143?
import java.util.*;
public class Test {public static int sum(ArrayList<Integer> tmp){int sum = 0;for(int i : tmp)sum += i;return sum;}public static void dfs(int[] S, int index, ArrayList<Integer> tmp, Set<ArrayList<Integer>> ret) {if( sum(tmp) == 29)ret.add(new ArrayList<Integer>(tmp));// 1 需要复制出来一个对象for (int i = index; i < S.length; i++) {tmp.add(S[i]);dfs(S, i + 1,tmp, ret);tmp.remove(tmp.size() - 1);}}public static void main(String[] args) {int a[] = {1, 3, 4, 2, 6,7,5,5,8,10,9,10,7,17};Set<ArrayList<Integer>> result = new HashSet<ArrayList<Integer>> ();dfs(a, 0,new ArrayList<Integer>(), result);System.out.println(result.size());}}
import copy
import operator
def answer1(a, answer_num, all_nums, all_num_list):
if len(a) == 1:
return 0
branch_sum_num = 0
for i in range(len(a)):
all_nums.append(a[i])
next_answer_num = answer_num - a[i]
if next_answer_num == 0:
all_num_list.append(all_nums)
branch_sum_num += 1
elif next_answer_num > 0:
b = copy.deepcopy(a)
b = b[i+1:]
next_all_nums = copy.deepcopy(all_nums)
branch_sum_num += answer1(b, next_answer_num, next_all_nums, all_num_list)
else:
all_nums.pop(-1)
continue
all_nums.pop(-1)
return branch_sum_num
def main():
a = [1, 3, 4, 2, 6, 7, 5, 5, 8, 10, 9, 10, 7, 17]
all_nums, all_num_list = list(), list()
branch_sum_num = answer1(a, 29, all_nums, all_num_list)
delete_index = list()
for i in range(len(all_num_list)):
for j in range(i + 1, len(all_num_list)):
if operator.eq(all_num_list[i], all_num_list[j]):
delete_index.append(j)
delete_index = list(set(delete_index))
delete_index.sort(reverse=True)
for i in delete_index:
all_num_list.pop(i)
print('all_num_list', all_num_list)
print(branch_sum_num - len(delete_index)) import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.Set;
public class testACM {
static Integer[] a = new Integer[20];
static int n;
static LinkedList<Integer> q = new LinkedList<Integer>();
static Set<LinkedList<Integer>> s = new HashSet<LinkedList<Integer>>();
public static void dfs(int index,int now) {
if(index == n+1 || now > 29) {
return;
}
now+=a[index];
q.add(a[index]);
if(now == 29) {
s.add(q);
q.remove(q.size()-1);
now-=a[index];
dfs(index+1,now);
return;
}
dfs(index+1,now);
q.remove(q.size()-1);
now-=a[index];
dfs(index+1,now);
}
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
n = reader.nextInt();
for(int i = 1; i<=n;i++) {
int x = reader.nextInt();
a[i] = Integer.valueOf(x);
}
dfs(1,0);
System.out.println(s.size());
} }
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
set<vector<int> >s;
int main()
{
int a[] = {1, 3, 4, 2, 6,7,5,5,8,10,9,10,7,17};
s.clear();
int num = 0;
for(int i = 1; i < (1 << 14); i++)
{
int sum = 0;
vector<int>vet;
vet.clear();
for(int j = 0; j < 14; j++)
{
if(i & (1 << j))
{
sum += a[j];
vet.push_back(a[j]);
}
}
sort(vet.begin(), vet.end());
if(sum == 29){
s.insert(vet);
}
}
set<vector<int> >::iterator it;
for(it = s.begin(); it != s.end(); it++)
{
vector<int>vet;
vet = *it;
for(int i = 0, sz = vet.size(); i < sz; i++)printf("%d ", vet[i]);puts("");
}
printf("%d\n", s.size());
return 0;
}