zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    微信JS SDK Demo
    两种方法实现在HTML页面加载完毕后运行某个js
    JS 页面加载触发事件 document.ready和onload的区别
    Thinkphp3.2添加QQ互联和新浪微博一键登录功能
    bootstrap-select实现下拉框多选效果
    Sass (Syntactically Awesome StyleSheets)
    常见MFC UI界面库[转]
    VTK序列图像的读取[转][改]
    c语言-格式控制字符 %XXd 用法
    3DSlicer源代码编译过程vs2008+windows xp [转]
  • 原文地址:https://www.cnblogs.com/nonames/p/12018010.html
Copyright © 2011-2022 走看看