P1115 最大子段和&P1719 最大加权矩形

上接:DP&图论 DAY 1 上午

这两个题本质是一个亚子,所以放一起啦
DPDPDPDPDPDPDPDP

P1115 最大子段和

题解

 因为题目要求的是一段连续的区间,所以前缀和搞暴力???

我们设置数组 f[ i ] 表示以 a[ i ] 结尾的最大连续子段和

那么转移??? 

1.接着上一段,继续构成一段连续的子段 continue the old life

2.自成一段  和过去 say goodbye

转移方程: 

ans记录最大值就好啦

代码

#include<bits/stdc++.h>

using namespace std;

inline int read()
{
    int ans=0;
    char last=' ',ch=getchar();
    while(ch<'0'||ch>'9') last=ch,ch=getchar();
    while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
    if(last=='-') ans=-ans;
    return ans;
}

const int maxn=2e5+10;
int n,ans;
int a[maxn];
int f[maxn];

int main()
{
    n=read();
    for(int i=1;i<=n;i++)
      a[i]=read();
    f[0]=0;f[1]=a[1];
    ans=a[1];
    for(int i=1;i<=n;i++)
    {
        f[i]=max(f[i-1]+a[i],a[i]);
        ans=max(ans,f[i]);
    }
    printf("%d
",ans);
    
    return 0;
}

P1719 最大加权矩形

题解

其实这个题就是上一个的变式,我们只需要把本题的二维转变成一维就好啦!

考虑枚举子矩阵的上下界

确定了上下界,就缩成了一维,此时只需要算 “该行” ,的最大 f[ ] 就好啦!

解释一下数组:

 a[ i ][ j ] :读入给出的矩阵

sum[ i ][ j ] :第 j 列,前 i 行的前缀和

其实这里的 就相当于上一个题的

代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>

using namespace std;

inline int read()
{
    int ans=0;
    char last=' ',ch=getchar();
    while(ch<'0'||ch>'9') last=ch,ch=getchar();
    while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
    if(last=='-') ans=-ans;
    return ans;
}

const int maxn=125;
int n,ans=-128;
int a[maxn][maxn],sum[maxn][maxn],f[maxn];

int main()
{
    n=read();
    for(int i=1;i<=n;i++)
       for(int j=1;j<=n;j++)
           a[i][j]=read(),sum[i][j]=sum[i-1][j]+a[i][j];

    for(int i=1;i<=n;i++)
      for(int j=i;j<=n;j++)   //枚举上下界 i~j 
      {
          memset(f,0,sizeof(f));
          for(int k=1;k<=n;k++)   //DP
            f[k]=max(f[k-1]+(sum[j][k]-sum[i-1][k]),(sum[j][k]-sum[i-1][k])),
            ans=max(ans,f[k]);
      }
    
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/11355924.html