UVA - 1330 City Game

City Game

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

无翻墙链接: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 }

 

转载于:https://www.cnblogs.com/D-O-Time/p/7648085.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值