• 计算几个数相加和为16


    ##

    /************************************************************************/
    /*        功能:计算几个数和是否等于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;
    }
  • 相关阅读:
    按钮-全选复选框 PENGHAO
    ASP.NET技术内幕的电子书中文版 PENGHAO
    hotmail和gmail 邮件中背景图片无效不显示的解决办法
    Silverlight之DataGrid的列格式化日期
    MS SQL基础
    JS获得当前地址栏url
    Javascript实现复制到剪贴板
    C#.NET画验证码与Cookie验证
    网站部署与定制
    操作SQL数据库常用语句
  • 原文地址:https://www.cnblogs.com/tinaluo/p/8134593.html
Copyright © 2020-2023  润新知