分治法

Posted swiftac

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分治法相关的知识,希望对你有一定的参考价值。

分治法求最大子序列和:

def calc(a, l, r):
    m = (l + r) >> 1
    if l == r:
        return a[l]
    leftsum = calc(a, l, m)
    rightsum = calc(a, m + 1, r)
    thissum = 0
    rightbordersum = 0
    leftbordersum = 0
    for i in range(m + 1, r + 1):
        thissum += a[i]
        rightbordersum = max(rightbordersum, thissum)
    thissum = 0
    for i in range(m, l - 1, -1):
        thissum += a[i]
        leftbordersum = max(leftbordersum, thissum)
    midsum = rightbordersum + leftbordersum
    return max(midsum, max(leftsum, rightsum))


n = eval(input())
a = list(map(int, input().split()))
res = calc(a, 0, n - 1)
print(res)

分治法求解凸包问题:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
pair<int, int> a[maxn];
pair<int, int> p[maxn];
int vis[maxn], used[maxn];
bool cmp(pair<int, int> a, pair<int, int> b) {
    if (a.first == b.first)
        return a.second < b.second;
    return a.first < b.first;
}
int calc(pair<int, int> a, pair<int, int> b, pair<int, int> c) {
    return a.first * b.second + c.first * a.second + b.first * c.second - c.first * b.second - b.first * a.second - a.first * c.second;
}
void dfs(int start, int last) {
    int id = -1, maxval = 0;
    if (start < last) {
        for (int i = start + 1; i < last; i++) {
            int temp = calc(a[start], a[i], a[last]);
            if (!temp)
                vis[i] = 1;
            if (temp > maxval) {
                maxval = temp;
                id = i;
            }
        }
    }
    else {
        for (int i = last - 1; i > start; i--) {
            int temp = calc(a[start], a[i], a[last]);
            if (!temp)
                vis[i] = 1;
            if (temp > maxval) {
                maxval = temp;
                id = i;
            }
        }
    }
    if (id != -1) {
        vis[id] = 1;
        dfs(start, id);
        dfs(id, last);
    }
}
int main() {
    int n, cnt = 0;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i].first >> a[i].second;
    }
    sort(a + 1, a + 1 + n, cmp);
    vis[1] = 1; vis[n] = 1;
    dfs(1, n);
    dfs(n, 1);
    for (int i = 1; i <= n; i++) {
        if (vis[i])
            p[++cnt] = a[i];
    }
    used[1] = used[cnt] = 1;
    cout << p[1].first << " " << p[1].second << endl;
    for (int i = 2; i < cnt; i++) {
        int temp = calc(p[1], p[cnt], p[i]);
        if (temp >= 0) {
            cout << p[i].first << " " << p[i].second << endl;
            used[i] = 1;
        }
    }
    cout << p[cnt].first << " " << p[cnt].second << endl;
    for (int i = 2; i < cnt; i++) {
        int temp = calc(p[1], p[cnt], p[i]);
        if (temp < 0 && !used[i]) {
            cout << p[i].first << " " << p[i].second << endl;
            used[i] = 1;
        }
    }
    return 0;
}

 

以上是关于分治法的主要内容,如果未能解决你的问题,请参考以下文章

棋盘覆盖问题——分治法——代码清晰易懂

递归与分治法

对分治法思想的体会及结对编程情况汇报

分治法

分治法 实现归并排序

算法分治法