码迷,mamicode.com
首页 > 其他好文 > 详细

线性DP之最大和问题

时间:2020-01-29 17:40:58      阅读:91      评论:0      收藏:0      [点我收藏+]

标签:can   设计   情况下   它的   void   序列   amp   大连   线性dp   

【最长子序列和】

问题定义:对于给定序列 a1,a2,a3……an 寻找它的某个连续子段,使得其和最大。

模板:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 110;
 5 const int inf=0x3f3f3f3f;
 6 
 7 int main()
 8 {
 9     int a[maxn], n;
10     cin>>n;
11     for(int i=1; i<=n; i++){
12         cin>>a[i];
13     }
14     int dp[maxn];
15     dp[0] = 0;
16     for(int i=1; i<=n; i++){
17         dp[i]=max(dp[i-1]+a[i], a[i]);///状态转移方程,表示以第i个数结尾的连续子序列的最大和
18     }
19     int maxs = -inf;
20     for(int i = 1; i <= n; i++)
21     {
22         if(maxs<dp[i])
23             maxs=dp[i];
24     }
25     cout<<maxs<<endl;
26     return 0;
27 }

【数字三角形】

给定一个由n行数字组成的数字三角形如下图所示。试设计一个算法,计算出从三角形的顶至底的一条路径,使该路径经过的数字总和最大。
 技术图片
对于给定的由n行数字组成的数字三角形,计算从三角形的顶至底的路径经过的数字和的最大值。

模板:

 1 /* */
 2 # include <bits/stdc++.h>
 3 # include <iostream>
 4 # include <cstdio>
 5 # define Max(a, b)(a>b?a:b)
 6 using namespace std;
 7 
 8 int main()
 9 {
10     long long int a[101][101];
11     int D[101][101];
12     int n, i, j;
13     scanf("%d", &n);
14     for( i=1; i<=n; i++ )
15     {
16         for( j=1; j<=i; j++ )
17         {
18             scanf("%d", &D[i][j]);
19         }
20     }
21     for( i=1; i<=n; i++ )
22     {
23         a[n][i] = D[n][i];
24     }
25     for( i=n-1; i>=1; i-- )
26     {
27         for( j=1; j<=i; j++ )
28         {
29             a[i][j] = max(a[i+1][j], a[i+1][j+1]) + D[i][j];
30         }
31     }
32     printf("%lld\n", a[1][1]);
33     return 0;
34 }

 

【最大子矩阵和】

我们都知道在一维情况下求最大连续子序列和的操作:

1 for(int i=1;i<=n;i++){
2     dp[i]=max(a[i],dp[i-1]+a[i]);
3 }

那么该怎么推广到二维情况下呢:(比如样例)

0 -2 -7 0

9 2 -6 2

-4 1 -4 1

-1 8 0 -2

步骤:

(1)求矩阵大小是1*k(k=1,2,3,4)

可以发现就是求每行的最大连续子序和

0 -2 -7 0  (ans=0,矩阵为[0])

9 2 -6 2  (ans=11,矩阵为[9 2])

……

(2)求矩阵大小是2*k(k=1,2,3,4)

这时我们可以在第1,2行或2,3行或3,4行找最大矩阵

对于矩阵:

0 -2 -7 0

9 2 -6 2

来说,最大矩阵是

 

因为我们取的是矩阵,肯定是竖着一列都取的,不可能这一列取到第i个元素,上一列取到第i-1个元素,这样我们就可以把要求的两行,两两加起来

9 0 -13 2

这样求出的最大连续子序和是9,这个结果也就是这个矩阵对应的最大矩阵和。

同理把

9 2 -6 2

-4 1 -4 1

-4 1 -4 1

-1 8 0 -2

也分别加起来,三种情况下求出的最大值,就是2*k大小矩阵的最大值

(3)同理,我们求3*k,4*k

模板:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 110;
 5 
 6 int a[maxn][maxn];///原矩阵
 7 int b[maxn][maxn];///b[i][j]表示从某一行加到第j行第k列的列项和
 8 int dp[maxn];///dp[i]表示以i列为结尾的最大矩阵和
 9 int mx=0, n;
10 
11 void solve(int j){
12     memset(dp,0,sizeof(dp));
13     for(int i=1;i<=n;i++){
14         dp[i] = max(b[j][i], dp[i-1]+b[j][i]);
15         mx = max(mx,dp[i]);
16     }
17 }
18 
19 int main()
20 {
21     scanf("%d",&n);
22     for(int i=1;i<=n;i++){
23         for(int j=1;j<=n;j++){
24             scanf("%d",&a[i][j]);
25         }
26     }
27 
28     for(int i=1;i<=n;i++){///从第i行开始加
29         memset(b,0,sizeof(b));
30         for(int j=i;j<=n;j++){///加到第j行
31             for(int k=1;k<=n;k++){///第j行各列的值
32                 b[j][k] = a[j][k]+b[j-1][k];
33             }
34             solve(j);
35         }
36     }
37     printf("%d\n",mx);
38     return 0;
39 }

线性DP之最大和问题

标签:can   设计   情况下   它的   void   序列   amp   大连   线性dp   

原文地址:https://www.cnblogs.com/wsy107316/p/12240646.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!