int trap(vector<int>& height) {
     int len = height.size();
     vector<int> max_left(len, 0);
     vector<int> max_right(len, 0);
     for(int i=1; i<len; i++) {
         max_left[i] = max(max_left[i-1], height[i-1]);
         max_right[len-1-i] = max(max_right[len-i], height[len-i]);
     }
     int sum = 0;
     for(int k=0; k<len;k++) {
         sum += max ( min(max_left[k], max_right[k]) - height[k], 0); 
     }
     return sum;
 }
Exemple #2
0
AbstractKDNode *KDTree::Build(__in std::vector<Triangle const *> const &set,
                              __in float3_t const &min,
                              __in float3_t const &max,
                              __in std::size_t depth) {
    if ((set.size() <= max_bucket_size_) || (depth > max_hierarchy_depth_)) {
        // std::tcerr << set.size();

        if (set.empty()) {
            return new KDNull();
        } else {
            return new KDLeaf(set);
        }
    }
    depth++;

    float3_t const range(max - min);

    std::size_t axis = ~0U;  // 分割次元
    float_t value = std::numeric_limits<float_t>::signaling_NaN();  // 分割位置

    // surface area heuristic
    float_t min_cost = std::numeric_limits<float_t>::max();

    // event
    struct open_close_event {
        bool operator<(open_close_event const &e) const {
            // value が等しい場合 open Event < close Event とする
            return (value < e.value) ? true : (value > e.value) ? false
                   : type < e.type;
        }

        bool type;  // event type: {false: open, true: close}
        float_t value;
    };

#define EVENT_UPDATE(v)                                         \
  {                                                             \
    float_t const r = v - min[k];                               \
    float_t const sa_left = a + b * r;                          \
    float_t const sa_right = a + b * (range[k] - r);            \
    float_t const cost = n_left * sa_left + n_right * sa_right; \
    if (min_cost > cost) {                                      \
      min_cost = cost;                                          \
      axis = k;                                                 \
      value = v;                                                \
    }                                                           \
  }

    std::vector<open_close_event> event_list(set.size() * 2);
    for (std::size_t k = 0; k < 3; ++k) {
        // init event list
        for (std::size_t i = 0, size = set.size(); i < size; ++i) {
            event_list[i].type = false;
            event_list[i].value = set[i]->min(k);  // 最小値
            event_list[i + size].type = true;
            event_list[i + size].value = set[i]->max(k) + EPSILON;  // 最大値
        }

        // sort event list
        std::sort(event_list.begin(), event_list.end());

        // compute min cost
        float_t const a = range[(k + 1) % 3] * range[(k + 2) % 3];
        float_t const b = range[(k + 1) % 3] + range[(k + 2) % 3];

        std::size_t n_left = 0;
        std::size_t n_right = set.size();
        {
            float_t const v = event_list[0].value - EPSILON;
            EVENT_UPDATE(v);
        }
        for (std::size_t i = 0, size = event_list.size(); i < size; ++i) {
            if (event_list[i].type) {
                n_right--;  // close event
            } else {
                n_left++;  // open event
            }

            float_t v = event_list[i].value;
            if ((i + 1) < size) {
                if (v == event_list[i + 1].value) {
                    continue;  // do not evalute
                }
                // v += (event_list[i+1].value - v) * float_t(0.5);
            } else {
                v += EPSILON;
            }

            EVENT_UPDATE(v);
        }
    }
#undef EVENT_UPDATE

    // 左右に分類
    std::vector<Triangle const *> set_left;
    std::vector<Triangle const *> set_right;

    for (std::size_t i = 0, size = set.size(); i < size; ++i) {
        switch (set[i]->Overlap(axis, value)) {
        case 1:
            set_left.push_back(set[i]);
            break;  // 左
        case 2:
            set_right.push_back(set[i]);
            break;  // 右
        case 3:
            set_left.push_back(set[i]);
            set_right.push_back(set[i]);
            break;  // 両方
        default:
            assert(!"bad Triangle::Overlap");
            break;
        }
    }

    // set.swap(std::vector<Triangle const *>()); // clear & trim

    // create nodes
    KDNode *node = new KDNode(axis, value);
    {
        float3_t max_left(max);
        max_left[axis] = value;
        node->SetChild(0, Build(set_left, min, max_left, depth));
    }
    {
        float3_t min_right(min);
        min_right[axis] = value;
        node->SetChild(1, Build(set_right, min_right, max, depth));
    }

    return node;
}