• 动态规划(入门):各种数字三角形


    一、一般的数字三角形:

            给一个由数字形成的三角形,要求从三角形的顶端开始走,走到最后一行,要求走的路径之和最大。对于一般的数字三角行,可以正着走,也可以反着走。建议最好正走,不然加强版的数字三角形倒着走走不出来。


    例题:

    描述
    示出了一个数字三角形。 请编一个程序计算从顶至底的某处的一条路
    径,使该路径所经过的数字的总和最大。
      每一步可沿左斜线向下或右斜线向下走;
      1<三角形行数<25;
      三角形中的数字为整数<1000;

    输入格式
    第一行为N,表示有N行
    后面N行表示三角形每条路的路径权
    输出格式
    路径所经过的数字的总和最大的答案
    测试样例1
    输入
    5
    7
    3 8
    8 1 0
    2 7 4 4
    4 5 2 6 5
    输出
    30


    正走代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 25+5;
    int maps[maxn][maxn];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            memset(maps,0,sizeof(maps));
            for(int i=1;i<=n;i++)//从1开始并且初始化为0可以直接从(1,1)开始走
                for(int j=1;j<=i;j++)
                    {
                        int now;
                        scanf("%d",&now);
                        maps[i][j] = max(maps[i-1][j],maps[i-1][j-1]) + now;
                    }
            int ans = 0;
            for(int i=1;i<=n;i++)
                ans = max(maps[n][i],ans);//正走在最后需要找出各个路径走到最后一行时最大的一个数;
            printf("%d
    ",ans);
        }
    }

    反走代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 25+5;
    int maps[maxn][maxn];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            memset(maps,0,sizeof(maps));
            for(int i=1;i<=n;i++)
                for(int j=1;j<=i;j++)
                    scanf("%d",&maps[i][j]);
            for(int i=n-1;i>=0;i--)
                for(int j=1;j<=i;j++)
                    maps[i][j] += max(maps[i+1][j],maps[i+1][j+1]);
            printf("%d
    ",maps[1][1]);//反走的优势就在于此处,最大值直接就在(1,1)产生
        }
    }
    


    二、过定点的数字三角形(加强版一)
            还是数字三角形,多了一个要求,就是需要走固定的一个点。这个题的想法很有意思,化一般为特殊,具体的做法就是将固定的点加上一个很大的数,在规划的过程中就一定会走过这个点,在输出的时候将这个很大的数减去就是正确答案。但是在加上一个很大的数的时候需要计算一下,不要加上一个很大的数的时候超范围了就很尴尬了。

    例题:
    描述
    数字三角形必须经过某一个点,使之走的路程和最大
    输入格式
    第1行n,表示n行 <=25
    第2到n+1行为每个的权值
    第n+2行为两个数x,y表示必须经过的点
    输出格式
    最大值
    测试样例1
    输入
    2
    1
    1 1
    1 1
    输出
    2

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 25 + 5;
    const int Max = 1e5;
    int maps[maxn][maxn];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            memset(maps,0,sizeof(maps));
            for(int i=1;i<=n;i++)
                for(int j=1;j<=i;j++)
                    scanf("%d",&maps[i][j]);
            int x,y;
            scanf("%d%d",&x,&y);
            maps[x][y] += Max;//加上最大就一定会走过此点
            for(int i=1;i<=n;i++)
                for(int j=1;j<=i;j++)
                    maps[i][j] += max(maps[i-1][j],maps[i-1][j-1]);
            int ans = 0;
            for(int i=1;i<=n;i++)
                ans = max(ans,maps[n][i]);
            printf("%d
    ",ans - Max);//最后输出的时候不要忘记减去Max
        }
    }
    

    三、数字三角形mod100(加强版二)
            这个题很能体现动态规划的思想,记录的主要是状态,下一个状态由前一个状态得到。
            首先开一个三维数组,三位数组的前两维用来记录行和列,第三维大小开100,即0~99.用来记录状态(思考为什么是0~99)(其实第三维就是用来记录这个位置可能得到的所有的答案),看是否有这个数字,当这个数字存在的时候将第三维,也就是的这个数字记录的true(其实就是记录每次%100所得到的答案),下一个行就在上一行true的情况下转移。第【0】【0】【0】,【0】【1】【0】记录为true。这个题是将所有可能的得到的答案全部记录下来,最后遍历看最大的值。(嘴笨说不清楚

    例题:
    描述
    数字三角形
    要求走到最后mod 100最大
    输入格式
    第1行n,表示n行 <=25
    第2到n+1行为每个的权值
    输出格式
    mod 100最大值
    测试样例1
    输入
    2
    1
    99 98
    输出
    99



    #include<bits/stdc++.h>
    using namespace std;
    const int Mod = 100;
    const int maxn = 25 + 5;
    int maps[maxn][maxn];
    bool dp[maxn][maxn][100];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            memset(maps,0,sizeof(maps));
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++)
                for(int j=1;j<=i;j++)
                    scanf("%d",&maps[i][j]);
            dp[0][0][0] = dp[0][1][0] = true;//这个初始化很重要
            for(int i=1;i<=n;i++)
                for(int j=1;j<=i;j++)
                {
                    for(int k=0;k<=99;k++)
                    {
                        int now;
                        if(dp[i-1][j][k])//当上一个这个数值存在时就可以加上当前状态的值
                        {
                            now = (maps[i][j] + k)%Mod;
                            dp[i][j][now] = true;
                        }
                        if(dp[i-1][j-1][k])
                        {
                            now = (maps[i][j] + k)%Mod;
                            dp[i][j][now] = true;
                        }
                    }
                }
            int ans = 0;
            for(int i=1;i<=n;i++)
                for(int k=0;k<=99;k++)
                {
                    if(dp[n][i][k])
                    {
                        ans = max(ans,k);
                    }
                }
            printf("%d
    ",ans);
        }
    }
    



  • 相关阅读:
    lambba表达式
    根据某个字段筛选list数据
    git和idea绑定
    gitee创建仓库
    用 Python 3 + PyQt5 擼了一個可以播放“任意”音樂的播放器
    zabbix 共享内存设置
    Zabbix高可用,实现zabbix的无缝切换,无故障时间
    python练习题100
    斐波那契数列python实现
    随机生成指定位数密码包括大小写数字特殊符号
  • 原文地址:https://www.cnblogs.com/GoldenFingers/p/9107366.html
Copyright © 2020-2023  润新知