玉蟾宫

 题目链接:https://www.luogu.org/problemnew/show/P4147

题目背景

有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。

题目描述

这片土地被分成N*M个格子,每个格子里写着'R'或者'F',R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda。

现在freda要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着'F'并且面积最大。

但是rainbow和freda的OI水平都弱爆了,找不出这块土地,而蓝兔也想看freda卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为S,它们每人给你S两银子。

输入输出格式

输入格式:

 

第一行两个整数N,M,表示矩形土地有N行M列。

接下来N行,每行M个用空格隔开的字符'F'或'R',描述了矩形土地。

 

输出格式:

 

输出一个整数,表示你能得到多少银子,即(3*最大'F'矩形土地面积)的值。

 

输入输出样例

输入样例#1: 
5 6 
R F F F F F 
F F F F F F 
R R R F F F 
F F F F F F 
F F F F F F
输出样例#1: 
45

说明

对于50%的数据,1<=N,M<=200

对于100%的数据,1<=N,M<=1000

 

 Sol one :悬线法。(详情参见王知昆dalao大佬的博客

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define LL long long
 7 #define RI register int
 8 using namespace std;
 9 const int INF = 0x7ffffff ;
10 const int N = 1000 + 10 ;
11 
12 inline int read() {
13     int k = 0 , f = 1 ; char c = getchar() ;
14     for( ; !isdigit(c) ; c = getchar())
15       if(c == '-') f = -1 ;
16     for( ; isdigit(c) ; c = getchar())
17       k = k*10 + c-'0' ;
18     return k*f ;
19 }
20 int n, m ; bool hh[N][N] ; int l[N][N], r[N][N], L[N][N], R[N][N], h[N][N] ;
21 
22 int main() {
23     n = read(), m = read() ;
24     for(int i=1;i<=n;i++)
25       for(int j=1;j<=m;j++) {
26            char cc ; cin>>cc ;
27            if(cc == 'F') hh[i][j] = 1 ;
28       }
29     for(int i=1;i<=n;i++) {
30         int t = 0 ;
31         for(int j=1;j<=m;j++) {
32             if(hh[i][j]) l[i][j] = t ;
33             else L[i][j] = 0, t = j ;
34         }
35         t = m+1 ;
36         for(int j=m;j;j--) {
37             if(hh[i][j]) r[i][j] = t ;
38             else R[i][j] = m+1, t = j ;
39         }
40     }
41     int ans = 0 ;
42     for(int i=1;i<=m;i++) R[0][i] = m+1 ;  // 第0行一定要做好标记 
43     for(int i=1;i<=n;i++)
44       for(int j=1;j<=m;j++) {
45           if(hh[i][j]) {
46               h[i][j] = h[i-1][j]+1 ;
47               L[i][j] = max(L[i-1][j],l[i][j]+1) ;
48               R[i][j] = min(R[i-1][j],r[i][j]-1) ;
49               ans = max(ans,h[i][j]*(R[i][j]-L[i][j]+1)) ;
50           }
51       }
52     printf("%d",ans*3) ;
53     return 0 ;
54 }

 

  Sol two : 单调栈。枚举矩形下届,然后按照这道题:Largest Rectangle in a Histogram做就可以了。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<stack>
 7 #define LL long long
 8 #define RI register int
 9 using namespace std;
10 const int INF = 0x7ffffff ;
11 const int N = 1000 + 10 ;
12 
13 inline int read() {
14     int k = 0 , f = 1 ; char c = getchar() ;
15     for( ; !isdigit(c) ; c = getchar())
16       if(c == '-') f = -1 ;
17     for( ; isdigit(c) ; c = getchar())
18       k = k*10 + c-'0' ;
19     return k*f ;
20 }
21 int n, m, ans = 0 ; int pos[N][N], l[N] ;
22 bool hh[N][N] ;
23 
24 inline void solve(int now) {
25     stack<int>s ;
26     for(int i=1;i<=m;i++) {
27         while(s.size() && pos[now][s.top()] >= pos[now][i]) ans = max(ans,(i-l[s.top()]-1)*pos[now][s.top()]), s.pop() ;
28         if(s.size()) l[i] = s.top() ; else l[i] = 0 ;  // 不初始化的话这里就要加else 
29         s.push(i) ;
30     }
31     while(s.size()) ans = max(ans,(m-l[s.top()])*pos[now][s.top()]), s.pop() ;
32 }    
33 
34 int main() {
35     n = read(), m = read() ;
36     for(int i=1;i<=n;i++) 
37       for(int j=1;j<=m;j++) {
38            char cc ; cin>>cc ;
39            if(cc == 'F') hh[i][j] = 1 ;
40       }
41     for(int i=1;i<=n;i++)
42       for(int j=1;j<=m;j++)
43         if(!hh[i][j]) pos[i][j] = 0 ; else pos[i][j] = pos[i-1][j]+1 ;
44     for(int i=1;i<=n;i++) solve(i) ;
45     printf("%d",ans*3) ;
46     return 0 ;
47 }

 

posted @ 2018-04-08 18:33  zubizakeli  阅读(317)  评论(0编辑  收藏  举报