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 }

 

 

你可能感兴趣的:(HDU)