题意:给出一个蛋糕,蛋糕有两种颜色组成,同一种颜色的可以切矩形,红蓝相间的可以切正方形。问你切出的蛋糕的最大周长
对于同一种颜色,很显然就是最大子矩形了。用悬线法搞定
对于红蓝相间的正方形,可以用DP解决。
定义dp[i][j]表示,以i,j为正方形右下角点的时候的最大边长。显然dp[i][j]=min(dp[i-1][j],dp[i][j-1])+1,但是有一个前提,那就是
map[i][j]!=map[i-1][j] && map[i][j]!=map[i][j-1]
另外还需要注意一点就是,对角线上的元素必须是相同的。比如
BB
BR 如果不注意判断对角线的元素,那么正方形会得出2*2
View Code
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 using namespace std; 5 6 char v[1002][1002]; 7 int h[1002],l[1002],r[1002],lm,rm; 8 int n,m; 9 10 int get_rectange(char c) //悬线法 11 { 12 int i,j,ans,temp; 13 ans=0; 14 for(i=1;i<=m;i++) 15 { 16 h[i]=0;l[i]=1;r[i]=m; 17 } 18 for(i=1;i<=n;i++) 19 { 20 lm=1; 21 for(j=1;j<=m;j++) 22 { 23 if(v[i][j]==c) 24 { 25 h[j]++; 26 if(lm>l[j]) 27 l[j]=lm; 28 } 29 else 30 { 31 h[j]=0; 32 l[j]=1; 33 r[j]=m; 34 lm=j+1; 35 } 36 } 37 rm=m; 38 for(j=m;j>=1;j--) 39 { 40 if(rm<r[j]) 41 r[j]=rm; 42 if(h[j]) 43 { 44 temp=2*(r[j]-l[j]+1)+2*h[j]; 45 if(temp>ans) 46 ans=temp; 47 } 48 else 49 rm=j-1; 50 } 51 } 52 return ans; 53 } 54 55 int dp[1002][1002]; 56 57 int min(int a,int b) 58 { 59 return a<b?a:b; 60 } 61 62 int DP() 63 { 64 memset(dp,0,sizeof(dp)); 65 int i,j,k,ans=0; 66 for(i=1;i<=n;i++) 67 { 68 for(j=1;j<=m;j++) 69 { 70 dp[i][j]=1; 71 if(v[i-1][j]!=v[i][j] && v[i][j]!=v[i][j-1]) 72 { 73 k=min(dp[i-1][j],dp[i][j-1]); 74 if(v[i-k][j-k]==v[i][j]) //判断对角线 75 k++; 76 if(k>dp[i][j]) 77 dp[i][j]=k; 78 } 79 if(dp[i][j]*4>ans) 80 ans=dp[i][j]*4; 81 } 82 } 83 return ans; 84 } 85 86 int main() 87 { 88 int i,j,cas,ansR,ansB,ansC,temp,o=1; 89 freopen("D:\\in.txt","r",stdin); 90 scanf("%d",&cas); 91 while(cas--) 92 { 93 scanf("%d%d",&n,&m); 94 for(i=1;i<=n;i++) 95 { 96 scanf("%*c"); 97 for(j=1;j<=m;j++) 98 { 99 scanf("%c",&v[i][j]); 100 } 101 } 102 ansR=get_rectange('R'); 103 ansB=get_rectange('B'); 104 for(i=1;i<=m;i++) 105 v[0][i]='*'; 106 for(i=0;i<=n;i++) 107 v[i][0]=v[i][m+1]='*'; 108 ansC=DP(); 109 if(ansR>ansC) 110 ansC=ansR; 111 if(ansB>ansC) 112 ansC=ansB; 113 printf("Case #%d: %d\n",o++,ansC); 114 } 115 return 0; 116 }