leetcode:1043. 分隔数组以得到最大和(dp)

题目:

在这里插入图片描述

分析:

显然的dp,

改题,分解成k部分的代码:

class Solution {
public:
int A[501][500];
int f(vector<int> v,int c,int k)
{
 if(A[c][k]!=-(1<<30)) return A[c][k];
 if(k==1)
 {
  int maxx=-(1<<30);
  for(int i=c;i<v.size();i++) maxx=max(maxx,v[i]);
  A[c][k]=maxx*(v.size()-c);
        cout<<c<<" "<<k<<" "<<A[c][k]<<endl;
  return A[c][k];
 }
 int maxx=-(1<<30);
 for(int i=c;i<=v.size()-k;i++)
 {
  maxx=max(maxx,v[i]);
  A[c][k]=max(A[c][k],(i-c+1)*maxx+f(v,i+1,k-1));
        if(A[c][k]==90) cout<<"??"<<i<<" "<<endl;
 }
    cout<<c<<" "<<k<<" "<<A[c][k]<<endl;
 return A[c][k];
}
    int maxSumAfterPartitioning(vector<int>& v, int k) {    
 for(int i=0;i<v.size();i++)
 {
  for(int j=0;j<=k;j++) A[i][j]=-(1<<30);
 }
 //从i开始包括i,其后面的,分成k组。 
 return f(v,0,k);
    }
};

自顶向下的dp超时:

int A[501][500];
int f(vector<int> v,vector<int> &A,int x,int k)
{
 if(x==v.size()) return 0;
 if(A[x]!=-(1<<30)) return A[x];
 if(x==v.size()-1) return v[x];
 int maxx=-(1<<30);
 for(int i=x;i<min(k+x,v.size());i++)
 {
  maxx=max(maxx,v[i]);
  A[x]=max(A[x],(i-x+1)*maxx+f(v,A,i+1,k));
 }
 return A[x];
}
int main()
{
 vector<int> v; 
 int k;
 vector<int> A(v.size(),-(1<<30));
 return f(v,A,0,k);
} 

改进版dp,不用回溯即可啊!

class Solution {
public:
    int maxSumAfterPartitioning(vector<int>& v, int k) {
 vector<int> A(v.size(),-(1<<30));
 //A[i]表示到i为止的最大值。
 A[0]=v[0];
 for(int i=1;i<v.size();i++)
 {
  for(int j=max(0,i-k+1);j<=i;j++)
  {
   int maxx=-(1<<30);
   for(int c=j;c<=i;c++) maxx=max(maxx,v[c]);
            if(j!=0)
   A[i]=max(A[i],A[j-1]+(i-j+1)*maxx);
            if(j==0)
   A[i]=max(A[i],(i-j+1)*maxx);
  }
  }
  return A[v.size()-1]; 
    }
};

结果:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值