##
/************************************************************************/ /* 功能:计算几个数和是否等于16 /* 日期:2017年12月 /* 作者:骆国辉 /************************************************************************/ #include <stdio.h> #include <stack> #include <vector> #include <time.h> class SumCombine { public: SumCombine(int* data, int length, int target_value) : numbers(data), num_length(length), target(target_value) { result_num = 0; } enum Result { EQUAL = 0, LARGER = 1, SMALLER = 2, INVALID_INDEX = 3, }; typedef std::vector<int> VecPath; struct FuncState { VecPath path; }; int sum_value(const VecPath& path) { int sum = 0; for (unsigned int i = 0; i < path.size(); i++) { sum += numbers[path[i]]; } return sum; } void print_path(const VecPath& path) { for (unsigned int i = 0; i < path.size(); i++) { printf("%d ", numbers[path[i]]); } printf(" "); } Result check_next(const VecPath& path, int index) { if (index >= num_length) return INVALID_INDEX; int sum = sum_value(path) + numbers[index]; return sum == target ? EQUAL : (sum > target ? LARGER : SMALLER); } void resolve() { int current = 0; bool done = false; std::stack<FuncState> func_stack; func_stack.push(FuncState()); do { /*numbers数组从左到右的顺序依次尝试; a~i表示下标索引 */ FuncState& fs = func_stack.top(); Result res = check_next(fs.path, current); switch (res) { case EQUAL: { fs.path.push_back(current); /*找到一条可用的路径*/ print_path(fs.path); result_num++; /*如满足的path为 a->e,将path弹出e,并继续检测f节点*/ fs.path.pop_back(); current++; break; } case LARGER: { current++; /*过大,尝试下个节点*/ break; } case SMALLER: { /*过小,添加到path,当前state不变,并压入新state,用于回溯; 但若已经是最后一个节点,不再添加到路径; 如当前stack为 [0] a 检测到 a->e 之和不足,stack更新为 [1] a->e [0] a 并继续处理f节点 */ if (current != num_length - 1) { FuncState newfs = fs; newfs.path.push_back(current); func_stack.push(newfs); } current++; break; } case INVALID_INDEX: { /*没有可作为路径第一个节点的节点,相当于1~9都曾经作为路径第一个节点处理过,停止循环*/ if (fs.path.empty()) { done = true; } else { /*当前path不可用,恢复到上个state,并继续往下处理,如当前stack为: [2] a->e->f [1] a->e [0] a 检测发现 a->e->f-> 不通,恢复为 a->e,并从g开始*/ current = fs.path.back() + 1; func_stack.pop(); } break; } default: break; } } while (!done); } int get_result_num() { return result_num; } private: int* numbers; int num_length; int target; int result_num; }; void test1() { int array[] = { 2, 3, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70 }; time_t startTime = time(NULL); SumCombine sc(array, sizeof(array) / sizeof(int), 20); sc.resolve(); printf("result_num=%d, usetime=%d ", sc.get_result_num(), (int)(time(NULL) - startTime)); } void test2() { int array[] = { 9, 5, 2, 3, 4, 1, 7, 6, 8 }; time_t startTime = time(NULL); SumCombine sc(array, sizeof(array) / sizeof(int), 16); sc.resolve(); printf("result_num=%d, usetime=%d ", sc.get_result_num(), (int)(time(NULL) - startTime)); } int main() { test1(); test2(); getchar(); return 0; }