ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

线性 DP - 数字三角形模型

2022-05-23 21:04:29  阅读:145  来源: 互联网

标签:路径 int i2 cin i1 线性 三角形 include DP


原题 : 数字三角形

https://www.acwing.com/problem/content/900/

题意

给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。

分析

对于每一个位置 (x, y), 只有两种可能,向右下走或者向下走
状态表示: f[x,y] 表示所有从 (x, y) 到 (n,n) 的路径,指标是路径数字和
状态计算: f[x,y] = max(f[x+1, y], f[x+1, y+1]) + nums[x,y]
(x, y) 处状态的计算依赖于 (x+1, y) 和 (x+1, y+1) 处的计算,由此按照子问题图的拓扑序构建循环。

代码

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 510;

int nums[N][N];

int f[N][N];

int main(){
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= i; j ++){
            cin >> nums[i][j];
        }
    }
    
    
    
    for(int x = n; x >= 1; x --)
        for(int y = 1; y <= x; y ++){
            f[x][y] = max(f[x+1][y], f[x+1][y+1]) + nums[x][y];
        }
    
    cout << f[1][1] << endl;
    
    return 0;
}

衍生题1 : 摘花生

https://www.acwing.com/problem/content/1017/

题意

Hello Kitty想摘点花生送给她喜欢的米老鼠。

她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。

地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就能摘走该它上面所有的花生。

Hello Kitty只能向东或向南走,不能向西或向北走。

问Hello Kitty最多能够摘到多少颗花生。

分析

状态表示,f[i,j] 表示 (1,1) 到 (i, j) 的所有路径,指标是经过路径上的花生数最大值。
状态计算:只能从左边或者上面走到当前位置
f[i,j] = max(f[i-1, j], f[i, j-1]) + w[i,j]

代码

#include <iostream>

using namespace std;

const int N = 110;

int f[N][N], w[N][N];

int main(){
    int r, c, t;
    cin >> t;
    while(t --){
        cin >> r >> c;
        for(int i = 1; i <= r; i ++){
            for(int j = 1; j <= c; j ++){
                cin >> w[i][j];
            }
        }
        f[1][1] = w[1][1];
        for(int i = 2; i <= r; i ++){
            f[i][1] = f[i-1][1] + w[i][1];
        }
        for(int i = 2; i <= c; i ++){
            f[1][i] = f[1][i-1] + w[1][i];
        }
        for(int i = 2; i <= r; i ++)
            for(int j = 2; j <= c; j ++){
                f[i][j] = max(f[i-1][j] , f[i][j-1]) + w[i][j];
            }
        cout << f[r][c] << endl;
    }
    
    return 0;
}

衍生题 2 : 最低通行费

https://www.acwing.com/problem/content/1020/

题意

一个商人穿过一个 N×N

的正方形的网格,去参加一个非常重要的商务活动。

他要从网格的左上角进,右下角出。

每穿越中间 1 个小方格,都要花费 1个单位时间。

商人必须在 (2N−1)个单位时间穿越出去。

而在经过中间的每个小方格时,都需要缴纳一定的费用。

这个商人期望在规定时间内用最少费用穿越出去。

请问至少需要多少费用?

注意:不能对角穿越各个小方格(即,只能向上下左右四个方向移动且不能离开网格)。

分析

这个题乍一看跟数字三角形好像有点不太一样,因为题目没有限制只能向下向右,但是分析限制条件最多走 2 N - 1 步,如果只向下向右,最少也要走 2 N - 1 步,因此只能向下向右走。
状态表示: f[i,j] 从 (1,1) 到 (i, j) 的所有路径,指标是费用和的最小值
状态计算:f[i,j] = min(f[i-1,j], f[i, j-1]) + w[i,j]

代码

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 110;

int f[N][N], w[N][N];

int main(){
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            cin >> w[i][j];
    
    f[1][1] = w[1][1];
    for(int i = 2; i <= n; i ++){
        f[i][1] = f[i-1][1] + w[i][1];
        f[1][i] = f[1][i-1] + w[1][i];
    }
    
    for(int i = 2; i <= n; i ++)
        for(int j = 2; j <= n; j ++){
            f[i][j] = min(f[i-1][j], f[i][j-1]) + w[i][j];
        }
    
    cout << f[n][n] << endl;
    
    return 0;
}

衍生题3 : 方格取数

https://www.acwing.com/problem/content/description/1029/

题意

一个二维的矩阵,要寻找两条从 (1, 1) 到 (n, n) 的路径,使得两条路径数字和最大,一条路径取过一个位置之后这个位置的数字就变成 0

分析

状态表示f[k, i1, i2] 表示从 (1, 1) 到 (i1 ,k-i1) 和 (i2, k-i2) 的路径,指标是路径数字和最大值。
状态计算,每个路径上一步有两种走法,组合起来有四种走法
f[k,i1, i2] = max(f[k-1, i1-1, i2], f[k-1, i1, i2-1], f[k-1, i1-1, i2-1], f[k-1, i1, i2]) + t
t = w[i1][k-i1] + w[i2][k-i2] if i1 != i2, t = w[i1][k-i1] if i1 == i2

代码

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 22;

int f[N][N][N], w[N][N];

int main(){
    int n;
    cin >> n;
    int a,b,c;
    while(cin >> a >> b >> c, a || b || c)w[a][b] = c;
        
    for(int k = 2; k <= n + n; k ++)
        for(int i1 = 1; i1 < k; i1 ++)
            for(int i2 = 1; i2 < k; i2++){
                int j1 = k - i1, j2 = k - i2;
                if(j1 <= n && j1 >=1 && j2 <= n && j2 >=1){
                    int t = w[i1][j1];
                    if(i1 != i2)t += w[i2][j2];
                    int& x = f[k][i1][i2];
                    x = max(x, f[k-1][i1-1][i2] + t);
                    x = max(x, f[k-1][i1-1][i2-1] + t);
                    x = max(x, f[k-1][i1][i2-1] + t);
                    x = max(x, f[k-1][i1][i2] + t);
                }
            }
    
    cout << f[n + n][n][n] << endl;
    
    return 0;
}

练习 :方格取数的同类题 - 传纸条

https://www.acwing.com/problem/content/277/

题意

题目比较长,翻译转化之后大概就是在一个矩阵上找两条从 (1, 1) 到 (m, n) 的路径,中间没有交点,且路径数字和最大

分析

直观上感觉这题跟上一题基本上一样,除了要求不能相交。但是直觉告诉我们在上一题的答案中,不相交的路径应该是较优的,因为矩阵上的数字总是非负的,直觉上绕开一下可以拿到更多。
严格证明参考 : https://www.acwing.com/solution/content/12389/
因此在上一题的代码上小改一下就可以了。

代码

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 110;

int f[N][N][N], w[N][N];

int main(){
    int m, n;
    cin >> m >> n;
    for(int i = 1; i <= m; i ++)
        for(int j = 1; j <= n; j ++)
            cin >> w[i][j];
            
    for(int k = 2; k <= m + n; k ++)
        for(int i1 = 1; i1 < k; i1 ++)
            for(int i2 = 1; i2 < k; i2 ++){
                int j1 = k - i1, j2 = k - i2;
                int t = w[i1][j1];
                if(i1 != i2)t += w[i2][j2];
                if(j1 >=1 && j1 <= n && j2 >= 1 && j2 <= n){
                    int& x = f[k][i1][i2];
                    x = max(x, f[k-1][i1][i2] + t);
                    x = max(x, f[k-1][i1-1][i2-1] + t);
                    x = max(x, f[k-1][i1-1][i2] + t);
                    x = max(x, f[k-1][i1][i2-1] + t);
                }
            }
    
    cout << f[m + n][m][m] << endl;
    
    return 0;
}

标签:路径,int,i2,cin,i1,线性,三角形,include,DP
来源: https://www.cnblogs.com/Softwarer1412/p/16302769.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有