LA_3029 City Game( DP )

題意:
一個由'R'和'F'組成的m*n的矩陣,求全部F的子矩陣最大,輸出結果*3.
分析:
比較容易想到的是枚舉每個矩陣的左上和右下的頂點然後統計,這樣的時間複雜度O(N^4)太慢了,其實可以把從i行到矩陣第一行看成一個一維數組,其中裏面的數字表示的就是這一列的高度,記up[i],表示第i列在第i行的高度,up的維護比較簡單,如果當前元素是'R'則up[i] = 0, 否則up[i] += 1,那麼答案就是枚舉每列,統計其向右向左的最大延伸距離,使用l, r, 數組標記,具體看Code.
Code:
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;


#define DIR     4
#define DIM     2
#define STATUS  2
#define MAXN    1000 + 10
#define MAXM    100000 + 10
#define oo      (~0u)>>1
#define INF     0x3F3F3F3F
#define REPI(i, s, e)   for(int i = s; i <= e; i ++)
#define REPD(i, e, s)   for(int i = e; i >= s; i --)


static const double EPS = 1e-5;


typedef struct ArcNode_ {
        int u, v, w, next;
}ArcNode;


int l[MAXN];
int r[MAXN];
int up[MAXN];
char g[MAXN][MAXN];


int scan(int n)
{
        REPI(i, 1, n) {
                l[i] = r[i] = i;
        }
        REPI(i, 2, n) {         //cal l.
                while( l[i] > 1 && up[i] <= up[l[i]-1] ) {
                        l[i] = l[l[i]-1];
                }
        }


        REPD(i, n-1, 1) {       //cal r.
                while( r[i] < n && up[i] <= up[r[i]+1] ) {
                        r[i] = r[r[i]+1];
                }
        }


        int sum = 0;
        REPI(i, 1, n) {
                sum = max(sum, (r[i]-l[i]+1)*up[i]);
        }
        return sum;
}


int cal(int n, int m)
{
        int ans = 0;
        memset(up, 0, sizeof(up));
        REPI(i, 1, n) {
                REPI(j, 1, m) {
                        up[j] = ( 'F' == g[i][j] )? up[j]+1 : 0;
                }
                ans = max(ans, scan(m));
        }
        return ans;
}


int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
        freopen("test.in", "r", stdin);
#endif
        int cas;
        int n;
        int m;
        char ch[2];


        scanf("%d", &cas);
        REPI(k, 1, cas) {
                scanf("%d %d", &n, &m);
                REPI(i, 1, n) {
                        getchar();
                        REPI(j, 1, m) {
                                scanf("%s", ch);
                                g[i][j] = *ch;
                        }
                }
                printf("%d\n", cal(n,m)*3);
        }
        return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值