UVA - 1330 City Game

City Game

FQ链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4076

无FQ链接:https://vjudge.net/problem/UVA-1330

 Solution

题目大意:给你一个只包含R和F的矩形,问你怎么选择一个子矩阵要求仅包含F,面积最大。(n,m<=1000)。
题解:此题看着可以暴搜,加上剪枝复杂度O(n*m*GG)。看看卡不卡了,总之很虚。
那么看看既然是子矩阵,那么就有一些特殊的性质,类似于暴搜的剪枝,如果上面一个元素不是F,那么矩阵就要中断。我们设U[i][j]代表,(i,j)所能向上拓展的最大高度,L[i][j]与R[i][j]分别代表左右,满足上界的最远距离坐标,那么这个就构成以个子矩阵了。可能会想,这个限制了L与R,会不会出现漏掉的情况呢?
答案是会!但不全会!例如:
RRRR
RRFR
RFFF
虽然在(3,3)的时候,答案是2(最优的答案是3啊!),但是一定会有(3,2)的时候来弥补,所以答案不会出错的。
那么我们就可以O(n*m)的转移方程了。如果这一位是R,那么U=0,否则U=上一层的U+1。L=max(上一层的L,这一层左边最近的一个R坐标+1)。注意是坐标,更好写。R类似,这样就可以统计出答案了。

 

 1 #include<queue>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 #define RG register
 8 #define LL long long
 9 #define fre(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
10 using namespace std;
11 const int MAXN=1010;
12 int Case,n,m,ans;
13 int U[MAXN][MAXN],L[MAXN][MAXN],R[MAXN][MAXN];
14 char s[MAXN][MAXN],g[10];
15 int main()
16 {
17    scanf("%d",&Case);
18    while(Case--)
19       {
20          scanf("%d%d",&n,&m);
21          for(int i=1;i<=n;i++)
22             {
23                for(int j=1;j<=m;j++)
24                   {
25                      scanf("%s",g);
26                      s[i][j]=g[0];
27                   }
28             }
29          ans=0;
30          for(int j=1;j<=m;j++)
31             U[1][j]=L[1][j]=R[1][j]=0;
32          for(int i=1;i<=n;i++)
33             {
34                int le=1,ri=m;
35                for(int j=1;j<=m;j++)
36                   {
37                      if(s[i][j]=='R')
38                         le=j+1;
39                      if(s[i][j]=='R')
40                         {
41                            U[i][j]=0;
42                            L[i][j]=1;
43                         }
44                      else
45                         {
46                            U[i][j]=U[i-1][j]+1;
47                            L[i][j]=max(L[i-1][j],le);
48                         }
49                   }
50                for(int j=m;j>=1;j--)
51                   {
52                      if(s[i][j]=='R')
53                         ri=j-1;
54                      if(s[i][j]=='R')
55                         R[i][j]=m;
56                      else
57                         R[i][j]=min(R[i-1][j]==0?0x3f3f3f3f:R[i-1][j],ri);
58                   }
59                for(int j=1;j<=m;j++)
60                   ans=max(ans,3*U[i][j]*(R[i][j]-L[i][j]+1));
61             }
62          printf("%d\n",ans);
63       }
64    return 0;
65 }

 

posted @ 2017-10-10 22:05  D_O_Time  阅读(612)  评论(0编辑  收藏  举报