hdu 4328 极大子矩形加正方形DP

题意:给出一个蛋糕,蛋糕有两种颜色组成,同一种颜色的可以切矩形,红蓝相间的可以切正方形。问你切出的蛋糕的最大周长

 

对于同一种颜色,很显然就是最大子矩形了。用悬线法搞定

 

对于红蓝相间的正方形,可以用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 }

 

 

posted @ 2012-10-11 10:51  Accept  阅读(336)  评论(0编辑  收藏  举报