区间DP tyvj 1466 最美妙的矩阵

来源:互联网 发布:数据更新维护机制 编辑:程序博客网 时间:2024/06/05 07:55

tyvj 1466 最美妙的矩阵
一个链接:http://hzwer.com/1811.html
题目分析:
这是一道区间DP,但我一开始连暴力都想复杂了。(QWQ)结果连30分的暴力都没想到!!!
解法一:其实这道题的暴力应该还是蛮好想的!分别枚举两个端点(一个左上,一个右下)然后暴力扫一遍区间,看是否合法即可,然后记录最大值。
解法二:我们优化一下上述思路,我们先预处理一下。用u[i][j]记录第i行第j列的数往上单调递减的最大值,再用一个can[i][j][k]数组表示第i行到第j行中的第k列是否能和k-1列合在一起。然后就可以DP了,我们用f[i][j][k]表示从第i行到第j行中的第k列能够得到的最大面积。然后写一个if判断一下就好,具体看代码中说明。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;int a[210][210],u[210][210],can[210][210][210],f[210][210][210];int ans,n,m;//a为原数组,用来存储输进来的值//u[i][j]表示第i行第j列的往上单调递减的最大值//can[i][j][k]表示第i行到第j行中的第k列能否满足要求//f[i][j][k]表示第i行到第j行中的第k列的子矩阵的最大面积 int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;++i)         for(int j=1;j<=m;++j)            scanf("%d",&a[i][j]);    for(int i=1;i<=n;++i)        for(int j=1;j<=m;++j)            if(a[i][j]>=a[i-1][j]) u[i][j]=u[i-1][j]+1;            else u[i][j]=1;    for(int i=1;i<=n;++i)        for(int j=i;j<=n;++j)            for(int k=1;k<=m;++k)                if((can[i][j-1][k]||j-1<i)&&j-i+1<=u[j][k]&&a[j][k]>=a[j][k-1])      //(can[i][j-1][k]||j-1<i)这个条件是表示前一行可以满足要求或者当前j等于i时都可以     //j-i+1<=u[j][k],在第j行第k列的位置上往上的单点递减区间长度得大于等于j-i+1     //a[j][k]>=a[j][k-1],同行之间也要满足单调递增                can[i][j][k]=1;    for(int i=1;i<=n;++i)        for(int j=i;j<=n;++j)            for(int k=1;k<=m;++k) {                if(can[i][j][k]) f[i][j][k]=f[i][j][k-1]+j-i+1;                //如果满足条件,那么就更新,这里在原来数组的基础上加上j-i+1,                //表示的是现在第i行到第j行的第k列可以加入进去                else if(u[j][k]>=j-i+1) f[i][j][k]=j-i+1;                //不能的话,如果u[j][k]>=j-i+1那就值赋值这一个单位宽度的区间面积                ans=max(ans,f[i][j][k]);//去一个最大值            }    printf("%d",ans);    return 0;   } 
原创粉丝点击