• dp入门题(数塔)


    http://acm.hdu.edu.cn/showproblem.php?pid=2084

    题意:

            7
          3      8
        8     1       0
      2       7     4       4
    4    5    2       6        5
    在上面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。
    路径上的每一步都只能往左下或右下走。只需要求出这个最大和即可,不必给出具体路径。
     
    解法1:dfs搜索每一条路径,可以发现很多点会重复搜索。时间复杂度为:O(2的n次方)
    //#include <bits/stdc++.h>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <string.h>
    #include<time.h>
    #include <vector>
    #define ME(x , y) memset(x , y , sizeof(x))
    #define SF(n) scanf("%d" , &n)
    #define rep(i , n) for(int i = 0 ; i < n ; i ++)
    #define INF  0x3f3f3f3f
    #define mod 20191117
    #define PI acos(-1)
    using namespace std;
    typedef long long ll ;
    int a[109][109];
    int n ;
    
    int getsum(int i , int j)
    {
        if(i == n)
            return a[i][j];
        else{
            int x = getsum(i+1 , j);
            int y = getsum(i+1 , j+1);
            return max(x , y) + a[i][j];
        }
    }
    
    int main()
    {
        /*#ifdef ONLINE_JUDGE
        #else
            freopen("D:/c++/in.txt", "r", stdin);
            freopen("D:/c++/out.txt", "w", stdout);
        #endif*/
        int t ;
        scanf("%d" , &t);
        while(t--)
        {
            memset(dp , -1 , sizeof(dp));
            scanf("%d" , &n);
            for(int i = 1 ; i <= n ; i++)
            {
                for(int j = 1 ; j <= i ; j++)
                {
                    scanf("%d" , &a[i][j]);
                }
            }
            cout << getsum(1 , 1) << endl ;
    
        }
    
    
        return 0;
    }
    

    解法1改进:记忆化搜索,将搜索过的点记录下来。时间复杂度O(n的平方)。

    //#include <bits/stdc++.h>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <string.h>
    #include<time.h>
    #include <vector>
    #define ME(x , y) memset(x , y , sizeof(x))
    #define SF(n) scanf("%d" , &n)
    #define rep(i , n) for(int i = 0 ; i < n ; i ++)
    #define INF  0x3f3f3f3f
    #define mod 20191117
    #define PI acos(-1)
    using namespace std;
    typedef long long ll ;
    int a[109][109];
    int n ;
    int dp[109][109];
    
    
    int getsum(int i , int j)
    {
        if(i == n)
            return a[i][j];
        else{
            if(dp[i][j] != -1) return dp[i][j];
            int x = getsum(i+1 , j);
            int y = getsum(i+1 , j+1);
            dp[i][j] = max(x,y)+a[i][j];
            return max(x , y) + a[i][j];
        }
        return dp[i][j] ;
    }
    
    
    int main()
    {
        /*#ifdef ONLINE_JUDGE
        #else
            freopen("D:/c++/in.txt", "r", stdin);
            freopen("D:/c++/out.txt", "w", stdout);
        #endif*/
        int t ;
        scanf("%d" , &t);
        while(t--)
        {
            memset(dp , -1 , sizeof(dp));
            scanf("%d" , &n);
            for(int i = 1 ; i <= n ; i++)
            {
                for(int j = 1 ; j <= i ; j++)
                {
                    scanf("%d" , &a[i][j]);
                }
            }
            cout << getsum(1 , 1) << endl ;
        }
    
    
        return 0;
    }
    

    解法2、递归转为递推。从底层向上递推。

    //#include <bits/stdc++.h>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <string.h>
    #include<time.h>
    #include <vector>
    #define ME(x , y) memset(x , y , sizeof(x))
    #define SF(n) scanf("%d" , &n)
    #define rep(i , n) for(int i = 0 ; i < n ; i ++)
    #define INF  0x3f3f3f3f
    #define mod 20191117
    #define PI acos(-1)
    using namespace std;
    typedef long long ll ;
    int a[109][109];
    int n ;
    int dp[109][109];
    
    
    
    int main()
    {
        /*#ifdef ONLINE_JUDGE
        #else
            freopen("D:/c++/in.txt", "r", stdin);
            freopen("D:/c++/out.txt", "w", stdout);
        #endif*/
        int t ;
        scanf("%d" , &t);
        while(t--)
        {
            memset(dp , -1 , sizeof(dp));
            scanf("%d" , &n);
            for(int i = 1 ; i <= n ; i++)
            {
                for(int j = 1 ; j <= i ; j++)
                {
                    scanf("%d" , &a[i][j]);
                }
            }
            for(int i = 1 ; i <= n ; i++)
            {
                dp[n][i] = a[n][i];
            }
            for(int i = n - 1 ; i >= 1 ; i--)
            {
                for(int j = 1 ; j <= i ; j++)
                {
                    dp[i][j] = max(dp[i+1][j] , dp[i+1][j+1])+a[i][j];
                }
            }
            cout << dp[1][1] << endl ;
        }
    
    
        return 0;
    }
    

    解法2优化空间

    //#include <bits/stdc++.h>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <string.h>
    #include<time.h>
    #include <vector>
    #define ME(x , y) memset(x , y , sizeof(x))
    #define SF(n) scanf("%d" , &n)
    #define rep(i , n) for(int i = 0 ; i < n ; i ++)
    #define INF  0x3f3f3f3f
    #define mod 20191117
    #define PI acos(-1)
    using namespace std;
    typedef long long ll ;
    int a[109][109];
    int n ;
    int dp[109];
    
    
    int main()
    {
        /*#ifdef ONLINE_JUDGE
        #else
            freopen("D:/c++/in.txt", "r", stdin);
            freopen("D:/c++/out.txt", "w", stdout);
        #endif*/
        int t ;
        scanf("%d" , &t);
        while(t--)
        {
            memset(dp , -1 , sizeof(dp));
            scanf("%d" , &n);
            for(int i = 1 ; i <= n ; i++)
            {
                for(int j = 1 ; j <= i ; j++)
                {
                    scanf("%d" , &a[i][j]);
                }
            }
            for(int i = 1 ; i <= n ; i++)
            {
                dp[i] = a[n][i];
            }
            for(int i = n - 1 ; i >= 1 ; i--)
            {
                for(int j = 1 ; j <= i ; j++)
                {
                    dp[j] = max(dp[j] , dp[j+1])+a[i][j];
                }
            }
            cout << dp[1] << endl ;
        }
    
    
        return 0;
    }
    
  • 相关阅读:
    vim 去掉自动注释和自动回车
    性别回归
    表情识别
    python list按字典的key值排序
    pytorch学习率策略
    python将list元素转为数字
    php面向对象
    mysql
    mysql
    mysql
  • 原文地址:https://www.cnblogs.com/nonames/p/12018010.html
Copyright © 2020-2023  润新知