【DP专题】——洛谷P2331最大子矩阵
简单的动规题。
传送门:GO
看到这题m<=2,先分类讨论一波:
m=1时,dp[i][j]表示到第i个点,选了j个矩阵的最大子矩阵。
状态转移方程:
dp[i][j]=dp[t][j-1]+sum[i]-sum[t]
意思是枚举一段区间,将它设为新的矩阵。
m=2时,设dp[i][j][k]表示第i行,状态为j,此时选到k个矩阵时的最大子矩阵。
设计状态:
1.空的
2.只选左边
3.只选右边
4.两边都选,但是左边和右边归为两个子矩阵
5.两边都选,分配到上面
分别讨论状态转移,大致有25个转移方程(好多)
具体看代码就可以了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int read(){ 4 int x=0,f=1; 5 char c=getchar(); 6 while(!isdigit(c)){ 7 if(c=='-') f=-1; 8 c=getchar(); 9 } 10 while(isdigit(c)){ 11 x=(x<<1)+(x<<3)+(c^48); 12 c=getchar(); 13 } 14 return x*f; 15 } 16 const int N=110; 17 int n,m,k; 18 int b[N]; 19 int f[N][15][10]; 20 int g[N][15]; 21 int main(){ 22 n=read();m=read();k=read(); 23 if(m==1){ 24 for(int i=1;i<=n;i++){ 25 b[i]=b[i-1]+read(); 26 } 27 for(int i=1;i<=k;i++){ 28 for(int j=1;j<=n;j++){ 29 g[j][i]=g[j-1][i]; 30 for(int l=1;l<j;l++){ 31 g[j][i]=max(g[j][i],g[l][i-1]+b[j]-b[l]); 32 } 33 } 34 } 35 printf("%d",g[n][k]); 36 return 0; 37 } 38 else{ 39 memset(f,-0x3f,sizeof(f)); 40 for(int i=0;i<=n;i++){ 41 for(int j=0;j<=k;j++){ 42 f[i][j][0]=0; 43 } 44 } 45 int l,r; 46 for(int i=1;i<=n;i++){ 47 l=read();r=read(); 48 for(int j=1;j<=k;j++){ 49 f[i][j][0]=max(max(max(max(f[i-1][j][0],f[i-1][j][1]),f[i-1][j][2]),f[i-1][j][3]),f[i-1][j][4]); 50 f[i][j][1]=max(max(max(max(f[i-1][j-1][0],f[i-1][j][1]),f[i-1][j-1][2]),f[i-1][j][3]),f[i-1][j-1][4])+l; 51 f[i][j][2]=max(max(max(max(f[i-1][j-1][0],f[i-1][j-1][1]),f[i-1][j][2]),f[i-1][j][3]),f[i-1][j-1][4])+r; 52 f[i][j][3]=max(max(f[i-1][j-1][1],f[i-1][j-1][2]),f[i-1][j][3])+l+r; 53 f[i][j][4]=max(max(max(max(f[i-1][j-1][0],f[i-1][j-1][1]),f[i-1][j-1][2]),f[i-1][j-1][3]),f[i-1][j][4])+l+r; 54 } 55 } 56 printf("%d",max(max(max(max(f[n][k][0],f[n][k][1]),f[n][k][2]),f[n][k][3]),f[n][k][4])); 57 return 0; 58 } 59 return 0; 60 61 }
——抓住了时间,却不会利用的人,终究也逃不过失败的命运。