关闭

[DP]【最大全零矩阵】【2015.7.9TEST】E

标签: testdp
549人阅读 评论(1) 收藏 举报
分类:

E
0.9 seconds, 32 MB
“ 于是乎,你至少证明了你智商比金天成高,也就说你证明了你不是低智儿童,不错不错。
然而这次, 我貌似也卡住了,你给我打下手吧。勇敢的少年啊快去创造奇迹!”
——-By Doctor Z
貌似 Z 博士正在解析 Zvangelion 初号机的一些问题, 中间遇到了困难。
Zvangelion 初号机有一块 R*S 的电路模块被某种 UMA 感染了。 为了方便我们用整数
描述每个单元的零件, 即用一个整数矩阵来表示该模块。
这种 UMA 的习性是,如果一块 N*M 的模块 S 被感染了(N,M>1), 那么它必然会让第
(1,1)(N,1)(1,M)和(N,M)上的元件保持( 意味着如果该电路被各种改动,都会满足) 以
下关系:( UMA 只会感染至少 2 行且至少 2 列的电路模块)
a[1][1] + a[N][M] ≤a[1][M] + a[N][1]
(注:a[i][j]表示矩阵中第 i 行第 j 列的数值)
然而, 谁说的一块电路不会被重复感染? 当一块电路被重复感染到,任意一个子电路模
块(即矩阵的一个子矩阵所表示的电路)都被感染了,那么这块电路就会发生可怕的事情,
对的, 就是异变!( 正确讲法应该是使徒化)
Z 博士需要知道, 这个 R*S 的电路模块中, 面积最大的有异变( 使徒化) 嫌疑的子电
路模块的面积是多少?
【 输入】
第一行两个正整数 R 和 S(2≤R,S≤1000),表示 Zvangelion 的电路模块大小。
下接一个 R 行 S 列的矩阵, 用整数来描述电路模块内 R*S 个电路单元上的元件。 描述所用
的整数分布在[-1000000,1000000]内。
【 输出】 面积最大的有异变(使徒化)嫌疑的子电路模块的面积。 如果没有则请输出 0.
【 测试样例】
Input
3 3
1 4 10
5 2 6
11 1 3
Output
9
Input
3 3
1 3 1
2 1 2
1 1 1
Output
4
Input
5 6
1 1 4 0 3 3
4 4 9 7 11 13
-3 -1 4 2 8 11
1 5 9 5 9 10
4 8 10 5 8 8
Output
15
着重解释第二个测试样例。如果整个电路模块都有变异嫌疑,那么要求的是 3*3 的矩
阵 1 个, 2*2 的矩阵共 4 个都满足被感染的条件。 然而观察发现左下角和右上角的 2*2 矩
阵并不满足要求。所以最大的面积既不可能是 9( 3*3),也不可能是 6( 2*3 或 3*2), 然
后左上角的 2*2 矩阵有变异嫌疑,故最大面积为 4( 2*2)。 第三个测试样例的变异模块为
从(3,2)开始一直到( 5,6)结束的子模块。
测试数据范围: 有 60%的数据满足 R、 S≤350

对于感染的条件,我们可以发现一个性质:
a b c
d e f
假设1.a+e<=b+d => a-b<=d-e
2.b+f<=c+e => b-c<=e-f
可以推出a-c<=d-f =>a+f<=c+d
这样一来这道题就能简化成一个求最大全零矩阵的问题。
对于1到r-1,1到s-1的点如果以它为左上方点的2*2矩阵为符合要求,就把这个点标记为0,否则就为1,然后就生成了长r-1,宽s-1的矩阵,答案就是最大的全0矩阵。

#include<cstdio>
#include<cstring>
#define maxl 1001

int r,s,ans=0;
int a[maxl][maxl];
int f[maxl][maxl],h[maxl],l[maxl],rr[maxl];

void prework()
{
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    scanf("%d%d",&r,&s);
    for(int i=1;i<=r;i++)
        for(int j=1;j<=s;j++)
            scanf("%d",&a[i][j]);
}

void mainwork()
{
    for(int i=1;i<=r-1;i++)
        for(int j=1;j<=s-1;j++)
        if(a[i][j]+a[i+1][j+1]<=a[i+1][j]+a[i][j+1])
            f[i][j]=0;
        else
            f[i][j]=1;
    for(int i=1;i<=r-1;i++)
    {
        for(int j=1;j<=s-1;j++)  //h[j]表示第i行第j列向上有多少个连续的0 ,下面枚举的矩阵就是以h[j]为高度 
        {
            if(f[i][j]==0)
                h[j]++;
            else
                h[j]=0;   //这一个是1就不能往下延续长度了 
        }
        for(int j=1;j<=s-1;j++)
        {
            l[j]=j;             //先假设这个高度为h[j]矩阵的左的边就是j 
            while(l[j]>1 && h[j]<=h[l[j]-1])//如果h[j]是小于h[l[j]-1],l[j]直接拓展到 l[l[j]-1]
                l[j]=l[l[j]-1];          //因为l[l[j]-1]是已经拓展过的对l[j]-1来说最左边的边,肯定是已经符合了要求的 
        }
        for(int j=s-1;j>=1;j--)     //和拓展左区间一样的做法 
        {
            rr[j]=j;
            while(rr[j]<s-1 && h[j]<=h[rr[j]+1])
                rr[j]=rr[rr[j]+1];
        }
        for(int j=1;j<=s-1;j++)     //找最大的矩阵,因为这里是缩点缩成的01矩阵,计算面积时长和宽要+1 
        {
            if(ans<(h[j]+1)*(rr[j]-l[j]+2))
                ans=(h[j]+1)*(rr[j]-l[j]+2);
        }
    }
}

void print()
{
    printf("%d",ans);
}

int main()
{
    prework();
    mainwork();
    print();
    return 0;
}
0
0

猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:10657次
    • 积分:685
    • 等级:
    • 排名:千里之外
    • 原创:55篇
    • 转载:0篇
    • 译文:0篇
    • 评论:16条