DP 最优二叉树 的四边形不等式优化

最优比例二叉树。代价函数cost 满足 对任意 a <= b <= c <= d 有 cost[a,c] + cost[b,d] <= cost[a,d] + cost[b,c]

可以证明其实是相等的 因为cost[a,b] = q[a- 1] + …… q[b] + p[a] + …… p[b];展开即可证明

所有对于dp也有同样的性质,所以可以用四边形不等式优化。

s[i,j]表示在决策中的 使解最优的决策变量的最大值

所以在每次转移的过程中枚举范围被大大降低了,总复杂度为O(n^2)

需要特殊处理的是,当第一次转移的时候,及区间范围l == 2的时候 beg = i,end = j;

第一个四边形不等式,HOHO~

#include <cstdio>

#include <cstring>

using namespace std;



const int SIZE = 201;

const int INF = 0x7fffff;

int p[SIZE], q[SIZE], n;

int result[SIZE][SIZE], cost[SIZE][SIZE],s[SIZE][SIZE];

void solve()

{

    for (int i = 1; i <= n; i++)

        result[i][i] = cost[i][i];

    int tmp, t;

    for (int l = 2; l <= n; l++)

    {

        for (int i = 1; i <= n - l + 1; i++)

        {

            tmp = INF;

            int j = i + l - 1;

            int beg = s[i][j - 1],end = s[i + 1][j];

            if (l == 2)

            {

                beg = i;

                end = j;

            }

            for (int k = beg; k <= end; k++)

            {

                t = result[i][k - 1] + result[k + 1][j] + cost[i][j];

                if (t <= tmp)

                {

                    tmp = t;

                    s[i][j] = k;

                }

            }

            result[i][j] = tmp;

        }

    }

    printf("%d\n", result[1][n]);

}



void preprocess()

{

    for (int i = 1; i <= n; i++)

        cost[i][i - 1] = q[i - 1];

    for (int i = 1; i <= n; i++)

        for (int j = i; j <= n; j++)

            cost[i][j] = cost[i][j - 1] + p[j] + q[j];

}



int main()

{

    while (scanf("%d",&n) == 1 && n)

    {

        for (int i = 1; i <= n; i++)

            scanf("%d", &p[i]);

        for (int i = 0; i <= n; i++)

            scanf("%d", &q[i]);

        preprocess();

        solve();

    }

    return 0;

}



你可能感兴趣的:(二叉树)