~$ 存档

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

##

/************************************************************************/
/*        功能:计算几个数和是否等于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("\n");
  }

  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\n", 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\n", sc.get_result_num(), (int)(time(NULL) - startTime));
}

int main() {
  test1();
  test2();
  getchar();
  return 0;
}

 

posted on 2017-12-28 11:05  LuoTian  阅读(865)  评论(0编辑  收藏  举报