poj 1964

来源:互联网 发布:木星探测器朱诺知乎 编辑:程序博客网 时间:2024/04/29 06:27

 转自http://blog.csdn.net/SMCwwh/article/details/5945855

题目大意是要你一个子矩阵,能使得覆盖未占用的连续区域最大

思路:动态规划

按行来划分状态,每次求出到当前行的区域最大覆盖区域

用height[i]表示第i列的当前行到达第1行未碰到占用方格的最大高度

l[i]表示当前行第i列能向左边扩展到坐标(不包含l[i]),即l[i]-1到i为连续区域

r[i]表示当前行第i列能向右边扩展到的坐标(不包含r[i]),即i到r[i] - 1为连续区域

所以扩展到当前行时第i列往左右扩展的连续区域大小为(r[i]-l[i]-1) * height[i]

从中选出最大的即为扩展到当前行的最大连续区域

 

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>using namespace std;const int maxn = 1010;int t, n, m;int height[maxn], l[maxn], r[maxn];int dp();int main(){        scanf("%d", &t);        while(t-- != 0)    {        memset(height, 0, sizeof(height));        memset(l, 0, sizeof(l));        memset(r, 0, sizeof(r));        scanf("%d %d", &n, &m);        int maxv = 0;        for(int i = 1; i <= n; i++)        {            for(int j = 1; j <= m; j++)            {                char s[3];                scanf("%s", s);                if(s[0] == 'F')                    height[j]++;                else                    height[j] = 0;            }                        int tmp = dp();            maxv = max(maxv, tmp);        }        printf("%d\n", maxv * 3);    }        return 0;}int dp(){    l[0] = l[m+1] = r[0] = r[m+1] = -1;    for(int i = 1; i <= m; i++)    {        if(height[i] > 0)        {            for(int j = i - 1; ; j = l[j])            {                if(height[j] < height[i])                {                    l[i] = j;                    break;                }            }        }                }        for(int i = m; i >= 1; i--)    {        if(height[i] > 0)        {            for(int j = i + 1; ; j = r[j])            {                if(height[j] < height[i])                {                    r[i] = j;                    break;                }            }        }    }        int maxv = 0;    for(int i = 1; i <= m; i++)    {        if(height[i] > 0)            maxv = max(maxv, (r[i] - l[i] - 1) * height[i]);    }    return maxv;}