[JOYOI1466] 最美妙的矩阵
题目限制
时间限制 | 内存限制 | 评测方式 | 题目来源 |
1000ms | 131072KiB | 标准比较器 | Local |
题目背景
Candy的生日即将到来,飘飘乎居士希望找到一个最美妙的矩阵送个Candy作为礼物
题目描述
飘飘乎居士从Pink处得知最美妙的矩阵满足三个条件:首先,它的长和宽都必须和矩阵的边界平行(也就是不可以出现斜的矩阵);第二:子矩阵横竖都要满足单调递增(可以相等,也就是对于每一个最优子矩阵的元素都要满足a[i][j]>=a[i-1][j] and a[i][j]>=a[i][j-1],其中a[i][j]表示矩阵第i行第j列的数字);第三:最优矩阵是在满足上述两个条件中面积最大的矩阵。
输入格式
第一行,两个正整数n,m
接下来n行,每行m个数字,构成一个n*m的矩阵
输出格式
一行,代表最优矩阵的面积
提示
最优子矩阵为
2 4 4
4 4 4
该矩阵满足横竖都单调递增,并且是所有满足条件中面积最大的。其中矩阵长为3宽为2,面积为6,也就是最后的答案。
对于30%的数据 0<n m<=50
对于100%的数据 0<n m<=200
对于所有数据 a[i][j]<=20000000
样例数据
输入样例 #1 | 输出样例 #1 |
---|---|
3 4 2 4 4 4 4 4 4 2 3 4 2 5 |
6 |
提交地址: JOYOI1466
题解:
我太菜了...
up[i][j] 表示(i, j)往上最多走多少
can[i][j][k]表示从第i行到第j行,第k列能否链接上第k-1列;
f[i][j][k]表示从i行到j行,到第k列时最大的面积
Code:
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 int n, m; 6 int a[210][210]; 7 int up[210][210]; 8 bool can[210][210][210]; 9 int f[210][210][210]; 10 int ans; 11 12 int main() 13 { 14 scanf("%d%d", &n, &m); 15 for (register int i = 1 ; i <= n ; i ++) 16 for (register int j = 1 ; j <= m ; j ++) 17 scanf("%d", &a[i][j]); 18 for (register int i = 1 ; i <= n ; i ++) 19 { 20 for (register int j = 1 ; j <= m ; j ++) 21 { 22 if (a[i][j] >= a[i-1][j]) up[i][j] = up[i-1][j] + 1; 23 else up[i][j] = 1; 24 } 25 } 26 27 for (register int i = 1 ; i <= n ; i ++) 28 { 29 for (register int j = i ; j <= n ; j ++) 30 { 31 for (register int k = 1 ; k <= m ; k ++) 32 { 33 if ((can[i][j-1][k] or j - i - 1 < 0) and up[j][k] >= j - i + 1 and a[j][k] >= a[j][k-1] and up[j][k-1] >= j - i + 1) can[i][j][k] = 1; 34 } 35 } 36 } 37 38 for (register int i = 1 ; i <= n ; i ++) 39 { 40 for (register int j = i ; j <= n ; j ++) 41 { 42 for (register int k = 1 ; k <= m ; k ++) 43 { 44 if (can[i][j][k]) f[i][j][k] = f[i][j][k-1] + j - i + 1; 45 else if (up[j][k] >= j - i + 1) f[i][j][k] = j - i + 1; 46 ans = max(ans, f[i][j][k]); 47 } 48 } 49 } 50 cout << ans << endl; 51 52 return 0; 53 }