uvalive 3029 City Game

https://vjudge.net/problem/UVALive-3029

题意:

给出一个只含有F和R字母的矩阵,求出全部为F的面积最大的矩阵并且输出它的面积乘以3。

思路:

求面积最大的子矩阵,可以用扫描线。参考训练指南(orz,虽然并不知道为什么用扫描线)。

对于每一个格子包含F,我们可以把它向上拉成一条悬线,直到上面的格子为R,然后观察这条悬线可以扫到左边与右边的最大距离,那么我们所求的面积就是所有的悬线中 悬线的长度乘以(右边界 - 左边界 + 1)的最大值。

然后,需要计算悬线的长度,用up来表示,那么当这个格子为F时up(i,j) = up(i - 1,j) + 1(i >= 1),up(i,j) = 1,(i == 0);

当这个格子为R时,up(i,j) = 0。

然后,用left数组和right数组维护左右边界的信息:

我们假设lo是当前格子之前的最近的是R的格子,从左往右遍历,那么 lo 的初值是-1,那么当(i,j) 为 F时 ,left(i,j) = max(left(i-1,j),lo + 1),为什么呢,因为当前的悬线如果是包含上一行此列的格子的话,那么就要考虑上一行左边的情况了;

当(i,j)为R时,left(i,j) = 0。

维护右边界的信息同理,不同的是求最小值和从右往左遍历。

!!!:记住一边遍历,一边维护。输入也是坑!

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 using namespace std;
  5 
  6 char a[1005][1005];
  7 int up[1005][1005],right[1005][1005],left[1005][1005];
  8 
  9 int main()
 10 {
 11     int t;
 12 
 13     scanf("%d",&t);
 14 
 15     while(t--)
 16     {
 17         int m,n;
 18 
 19         memset(a,0,sizeof(a));
 20         memset(up,0,sizeof(up));
 21         memset(right,0,sizeof(right));
 22         memset(left,0,sizeof(left));
 23 
 24         scanf("%d%d",&m,&n);
 25 
 26         getchar();
 27 
 28         for (int i = 0;i < m;i++)
 29             for (int j = 0;j < n;j++)
 30         {
 31             char s;
 32 
 33             s = getchar();
 34 
 35             while (s != 'R' && s != 'F') s = getchar();
 36 
 37             if (s == 'R') a[i][j] = 0;
 38             else a[i][j] = 1;
 39         }
 40 
 41         /*for (int i= 0;i < m;i++)
 42         {
 43             for (int j = 0;j < n;j++) printf("%d",(int)a[i][j]);
 44 
 45             printf("\n");
 46         }*/
 47 
 48         int ans = 0;
 49 
 50         for (int i = 0;i < m;i++)
 51         {
 52             for (int j = 0;j < n;j++)
 53             {
 54                 if (i == 0)
 55                 {
 56                     up[i][j] = a[i][j];
 57                 }
 58                 else
 59                 {
 60                     if (a[i][j]) up[i][j] = up[i-1][j] + 1;
 61                     else up[i][j] = 0;
 62                 }
 63             }
 64 
 65             int lo = -1,ro = n;
 66 
 67             if (i == 0)
 68             {
 69                 for (int j = 0;j < n;j++)
 70                 {
 71                     if (a[i][j] == 0) left[i][j] = 0, lo = j;
 72                     else left[i][j] = lo + 1;
 73                 }
 74 
 75                 for (int j = n - 1;j >= 0;j--)
 76                 {
 77                     if (a[i][j] == 0) right[i][j] = n, ro = j;
 78                     else right[i][j] = ro - 1;
 79                 }
 80 
 81                 for (int j = 0;j < n;j++)
 82                 {
 83                     int tmp = up[i][j] * (right[i][j] - left[i][j] + 1);
 84 
 85                     ans = max(ans,tmp * 3);
 86                 }
 87             }
 88             else
 89             {
 90                 for (int j = 0;j < n;j++)
 91                 {
 92                     if (a[i][j] == 0) left[i][j] = 0, lo = j;
 93                     else left[i][j] = max(lo + 1,left[i-1][j]);
 94                 }
 95 
 96                 for (int j = n - 1;j >= 0;j--)
 97                 {
 98                     if (a[i][j] == 0) right[i][j] = n, ro = j;
 99                     else right[i][j] = min(ro - 1,right[i-1][j]);
100                 }
101 
102                 for (int j = 0;j < n;j++)
103                 {
104                     int tmp = up[i][j] * (right[i][j] - left[i][j] + 1);
105 
106                     ans = max(ans,tmp * 3);
107                 }
108             }
109         }
110 
111         /*for (int i = 0;i < m;i++)
112         {
113             for (int j = 0;j < n;j++)
114             {
115                 printf("%d %d %d\n",up[i][j],left[i][j],right[i][j]);
116             }
117         }*/
118 
119         printf("%d\n",ans);
120     }
121 
122     return 0;
123 }

 

posted @ 2017-10-03 14:23  qrfkickit  阅读(221)  评论(0编辑  收藏  举报