Steel Strip Cutting - Introduction to Algorithms

top-down solution

Decomposition: Turn the steel bar cutting problem of length n into a sub-problem of length n-1 after cutting with the i subscript.
Solution sub-problem recursively, each time the length parameter is -1, and recurse when n=0, that is, no cutting is required Termination
Merge :
1. The solution of each subproblem + the arr[i] value of the cutting length of the previous section becomes the optimal solution of the previous subproblem
2. The optimal solution in the original scale problem is the one with the largest value among the solutions of all subproblems

//自顶向下
int max_sum(int arr[], int n)
{
    if (n == 0) {
        return 0;
    }
    int i = 0;
    int maxn = INT_MIN;
    int sum = 0;
    //边界,最后一次切割点是arr[n-1]+0
    for (i = 1; i <= n; i++) {
        sum = arr[i-1] + max_sum(arr, n - i);
        if (maxn < sum) {
            maxn = sum;
        }
    }
    return maxn;
}

Why is it slow?
Repeatedly calling itself recursively with the same parameters, repeatedly solving the same subproblems. O(2^n)

top down with memo

Still written in a top-down approach, but saving the solution to each subproblem along the way.
Knock on the key point: save the sub-problem solution during the process, and check whether the solution is saved before each recursion.

//带备忘的自顶向下
#define N  100
int maxArr[N];
void init(int maxArr[N])
{
    for (int i = 0; i < N; i++) {
        maxArr[i] = INT_MIN;
    }
}
int m_max_sum(int arr[], int n)
{   
    //检查
    if (maxArr[n] > INT_MIN) {
        return maxArr[n];
    }
    if (n == 0) {
        return 0;
    }
    int i = 0;
    int maxn = INT_MIN;
    int sum = 0;
    for (i = 1; i <= n; i++) {
        sum = arr[i - 1] + max_sum(arr, n - i);
        if (maxn < sum) {
            maxn = sum;
        }
    }
    //保存
    maxArr[n] = maxn;
    return maxn;
}

Self-improvement

This approach generally requires that the subproblem "size" is properly defined so that the solution of any subproblem depends only on the solution of the "smaller" subproblem. Therefore, we solve the subproblems from small to large . When solving a sub-problem, the smaller sub-problems it depends on have been solved and the results have been saved, so each sub-problem is solved only once, and when we solve it, all its premise sub-problems have been solved.
The above are the original words from the book that I typed by hand. Every sentence is very incisive and every word is pearly.

//自底向上
int btm_up(int arr[], int n)
{
    int j = 0, i = 0;
    int maxnn = INT_MIN;
    int sum = 0;
    //最小规模的解
    maxArr[0] = 0;
    //规模为j的子问题
    for (j = 1; j <= n; j++) {
        //求解规模为i的子问题与原来方法一样,只是规模i < j,所以在求规模j的时候不需要递归
        for (i = 1; i <= j; i++) {
            sum = arr[i - 1] + maxArr[j - i];
            if (sum > maxnn) {
                maxnn = sum;
            }
        }
        maxArr[j] = maxnn;
    }
    return maxArr[n];
}

reconstruction solution

For each sub-problem, not only the optimal value, but also the cutting point is saved, and the optimal solution is output by using this information.

//最后pos[n]就是最优的切割点
int pos[N] = { 0 };
//自底向上重构解
int btm_up_op(int arr[], int n)
{
    int j = 0, i = 0;
    int maxnn = INT_MIN;
    int sum = 0;
    //最小规模的解
    maxArr[0] = 0;
    //规模为j的子问题
    for (j = 1; j <= n; j++) {
        //在每个j规模下,maxnn是最优价格,pos[j]存的是前一段最优切割长度
        for (i = 1; i <= j; i++) {
            sum = arr[i - 1] + maxArr[j - i];
            if (sum > maxnn) {
                maxnn = sum;
                pos[j] = i;
            }
        }
        maxArr[j] = maxnn;
    }
    return maxArr[n];
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325904832&siteId=291194637