zoukankan      html  css  js  c++  java
  • 动态规划初步 刘汝佳字数 数字三角形

    有一个由非负整数组成的三角形,第一行只有一个数,除了最下行之外每个数左下方和右下方各有一个数 如图所示

     

    从第一行的数开始,每次可以往左下或右下走一格,直到走到最下行,把沿途经过的数全部加起来,如何走才能使得这个和最大?

    分析:

    一看到题目我们很自然的可以想到用回溯法(DFS)做,即每次都选择靠左的格子走,走到头后再回溯选择靠右的格子,按<左,右>的顺序遍历完所有的路径

    代码如下:

    #include<iostream>
    using namespace std;
    
    int a[11] = {0,29,9,5,12,7,26,6,14,15,8};//假设有四层
    int max = -1, sum = 0;
    int shuzi(int i, int j)//计算第i层第j个的数字在a数组的第几个
    {
        int x = 0;
        for (int l = 1; l <= i - 1; l++)
        {
            x += l;
        }
        x += j;
        return x;
    }
    int dfs(int i, int j)
    {
        if (i==5)
        {
            if (sum > max)
                max = sum;
            return 0;
        }
        sum += a[shuzi(i, j)];
        dfs(i + 1, j);
        dfs(i + 1, j + 1);
        sum -= a[shuzi(i, j)];
        return 0;
    }
    int main(int argc, char* argv[])
    {
        dfs(1, 1);
        cout << max<<endl;
        return 0;
    }

    时间复杂度是2^n,指数级的,n一旦大了就会超时

    所以用状态转移方程来发现每项的依赖项

    方程如下:

    d(i,j)=a(i,j)+max{d(i+1,j),d(i+1,j+1)};

    代码如下:

    #include<iostream>
    using namespace std;
    
    int a[20] = {0,1,2,3,4,5,6,7,8,9,12,0,0,0,0,0,0,0,0,0};
    int max(int a, int b)
    {
        return a > b ? a : b;
    }
    int shuzhi(int i, int j)
    {
        int x = 0;
        for (int l = 1; l <= i - 1; l++)
        {
            x += l;
        }
        x += j;
        return x;
    }
    int solve(int i, int j)
    {
        int x=shuzhi(i, j);
        return a[x]+(i==4?0:max(solve(i+1,j),solve(i+1,j+1)));
        
    }
    int main(int argc, char* argv[])
    {
        cout << solve(1, 1)<<endl;
        return 0;
    }

    已经知道了每项的依赖项,就可以避免重复计算

    #include<iostream>
    using namespace std;
    
    int a[20] = {0,13,11,8,12,7,26,6,14,15,8};
    int dp[10][10] = { {0,0} };
    int max(int a, int b)
    {
        return a > b ? a : b;
    }
    int shuzi(int i, int j)
    {
        int x = 0;
        for (int l = 1; l <= i - 1; l++)
        {
            x += l;
        }
        x += j;
        return x;
    }
    int solve(int i, int j)
    {
        for (int k = 1; k <= 4; k++)
            dp[4][k] = a[shuzi(4, k)];
        for (int k = 3; k >= 1; k--)
            for (int l = 1; l <= k; l++)
                dp[k][l] = a[shuzi(k, l)]+ max(dp[k + 1][l], dp[k + 1][l + 1]);
        return dp[i][j];
    }
    int main(int argc, char* argv[])
    {
        cout << solve(1, 1) << endl;
        return 0;
    }

    简化版:

    #include<iostream>
    using namespace std;
    
    int a[20] = { 0,1,2,3,4,5,6,7,8,9,10};
    int dp[10][10] = { { 0,0 } };
    int max(int a, int b)
    {
        return a > b ? a : b;
    }
    int shuzi(int i, int j)
    {
        int x = 0;
        for (int l = 1; l <= i - 1; l++)
        {
            x += l;
        }
        x += j;
        return x;
    }
    int solve(int i, int j)
    {
        if (dp[i][j] >= 0) return dp[i][j];
        return a[shuzi(i, j)] + (i==4?0:max(solve(i+1,j), solve(i + 1, j+1)));
    
    }
    int main(int argc, char* argv[])
    {
        memset(dp, -1, sizeof(dp));
        cout << solve(1, 1) << endl;
        return 0;
    }
  • 相关阅读:
    Lintcode415-Valid Palindrome-Medium
    Lintcode455-StudentID-Easy
    Lintcode241-String to Integer
    Lintcode521-Remove Duplicate Numbers in Array-Easy
    Lintcode214-Max of Array-Naive
    面试一个小公司,TPM相关概念
    C#, introduction, general
    make命令和makefile
    OS_Architecture_MemoryHierarchy
    Leecode_98_Validate_Binary_Search_Tree
  • 原文地址:https://www.cnblogs.com/seamusopen/p/9924628.html
Copyright © 2011-2022 走看看