fijk表示第一列选了i个第二列选了j个已经搞定了k个子矩阵的情况
然后考虑转移,可以不选,从上面转移作为初值,可以选,于是枚举之前的进行转移就行
实际上我们看到了m<=2并想到了分类转移的思想的时候已经变得很简单了
听说丽洁姐姐的博客里面有详细,但是并不能打开【大概是RP不好
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #define LL long long #define fo(i,a,b) for(int i=a;i<=b;i++) #define down(i,a,b) for(int i=a;i>=b;i--) using namespace std; inline LL read() { LL d=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();} return d*f; } #define N 105 #define M 15 #define NM 5 int a[N][M],s[N][M]; int f[N][N][M]; int n,m,nm,ans=0; void init() { memset(s,0,sizeof(s)); n=read(),m=read(),nm=read(); fo(i,1,n) { fo(j,1,m) { int x=read(); a[i][j]=x; s[i][j]=s[i-1][j]+a[i][j]; } } } void ini() { memset(s,0,sizeof(s)); scanf("%d%d%d",&n,&m,&nm); fo(i,1,n) { fo(j,1,m) { int x; scanf("%d",&x); a[i][j]=x; s[i][j]=s[i-1][j]+a[i][j]; } } } void DP() { memset(f,0,sizeof(f)); fo(p,1,nm) fo(i,1,n) fo(j,1,n) { f[i][j][p]=max(f[i-1][j][p],f[i][j-1][p]); fo(q,0,max(i,j)-1) { if(i==j) { f[i][j][p]=max(f[i][j][p],f[q][q][p-1]+s[i][1]-s[q][1]+s[j][2]-s[q][2]); } if(q<j)f[i][j][p]=max(f[i][j][p],f[i][q][p-1]+s[j][2]-s[q][2]); if(q<i)f[i][j][p]=max(f[i][j][p],f[q][j][p-1]+s[i][1]-s[q][1]); } } } void OUT() { cout<<f[n][n][nm]<<endl; } int main() { ini(); DP(); OUT(); return 0; }