[bzoj1910] [Ctsc2002] Award 颁奖典礼
应该是第一次写这种图形类的DP。。
一个“I”可以分成三个矩形。。令f[1..3][i][j][k]表示第几个矩形,下边界为第i行的j~k列,的最大面积。
然后就是各种优化啊什么的。。。时间复杂度O(nm²)
一开始一个辅助的区间DP写挂然后调了半天TAT
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int maxn=205; 6 const int inf=1002333; 7 int f[2][3][maxn][maxn]; 8 int sm[maxn][maxn],mx1[maxn][maxn],mx2[maxn][maxn]; 9 int n,m,pre,now,ans,tmpmx; 10 11 int ra;char rx; 12 inline int read(){ 13 rx=getchar(),ra=0; 14 while(rx<'0'||rx>'9')rx=getchar(); 15 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 16 } 17 inline int max(int a,int b){return a>b?a:b;} 18 inline int min(int a,int b){return a<b?a:b;} 19 int main(){ 20 register int i,j,k; 21 n=read(),m=read(); 22 for(i=1;i<=n;i++) 23 for(j=1;j<=m;j++)sm[i][j]=sm[i][j-1]+read(); 24 for(i=1;i<=m;i++)sm[0][i]=i; 25 26 now=1,pre=0; 27 for(i=1;i<=2;i++)memset(f[0][i],200,sizeof(f[0][i])); 28 for(i=1;i<=n;i++,swap(now,pre)){ 29 for(j=1;j<m;j++)for(k=j+1;k<=m;k++) 30 if(sm[i][k]==sm[i][j-1]) 31 f[now][0][j][k]=(sm[i-1][k]==sm[i-1][j-1]?f[pre][0][j][k]:0)+k-j+1; 32 else f[now][0][j][k]=-inf; 33 34 35 for(j=1;j<m;j++)for(k=m,tmpmx=-inf;k>j;k--) 36 tmpmx=max(tmpmx,f[pre][0][j][k]), 37 mx1[j][k]=max(mx1[j-1][k],tmpmx); 38 for(j=2;j<m;j++)for(k=j;k<m;k++) 39 if(sm[i][k]==sm[i][j-1]){ 40 f[now][1][j][k]=f[pre][1][j][k]+k-j+1; 41 if(sm[i-1][k+1]==sm[i-1][j-2]) 42 f[now][1][j][k]=max(f[now][1][j][k],mx1[j-1][k+1]+k-j+1); 43 } 44 else f[now][1][j][k]=-inf; 45 46 47 for(j=2;j<m;j++)mx2[j][j]=f[pre][1][j][j]; 48 for(j=1;j<m;j++) 49 for(k=2;k<m-j;k++) 50 mx2[k][k+j]=max(mx2[k][k+j-1],max(mx2[k+1][k+j],f[pre][1][k][k+j])); 51 52 for(j=1;j<m;j++)for(k=j+2;k<=m;k++){ 53 if(sm[i][k]==sm[i][j-1]) 54 f[now][2][j][k]=max(f[pre][2][j][k],mx2[j+1][k-1])+k-j+1; 55 else f[now][2][j][k]=-inf; 56 if(f[now][2][j][k]>ans)ans=f[now][2][j][k]; 57 } 58 } 59 printf("%d\n",ans); 60 return 0; 61 }