HDU 1506 1505 2870 2830
2017-07-09 00:00
260 查看
摘要: 动态规划 矩形面积最大值
1506 连续矩形最大面积
1505
题目大意:给出一个n * m 的矩形,求全为F的矩形面积最大。
题目思路:这道题和HDU1506很像。
d[i][j]表示第i行j列元素在前i行中的最大高度。(以第一行为底)例如测试样例:
然后和HDU-1506思路一样,
找出以当前点位最低点能左右延伸的最长距离,也就是找出最左最右的下标,最后的 ans = max(num[i]*(r[i]-l[i]+1))
2830
分析:扫描每一行,以该行作为底,用dp存放每一列1达到的高度,然后将高度排序(当然,不能直接对dp排序,因为扫下一行的有用),很容易就能找出最大的面积.最后就可以找出整体的最大值了
2870
题意:一个由字符a,b,c,w,x,y,z组成的矩阵,其中w,x,y,z可以转换成a,b,c中的某几个字符,问该矩阵可以组成的由相同字符构成的最大子矩阵。
分析:DP。首先想到要求的子矩阵一定是由相同字符构成的,所以可以枚举w,x,y,z分别转换成a,b,c后得到的最大子矩阵即可。
枚举最大矩形是由哪个字母构成的
1506 连续矩形最大面积
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL long long int const MAX = 1e6 + 1; int const INF = 1 << 30; using namespace std; //分别记录第i个柱子的高度和左右能够延伸的最远的柱子 LL H[MAX], L[MAX], R[MAX]; int main(int argc, char*argv[]) { int n; while ( scanf("%d", &n) == 1 && n ) { for ( int i = 1; i <= n; i++ ) { scanf("%lld", H + i); L[i] = i; R[i] = i; } //由第2个开始更新左边,L[i]表示第i个矩形可以延伸到的最左边的柱子 //L[i]-1 就是最左边柱子的左边 for ( int i = 2; i <= n; i++ ) { while ( H[L[i] - 1] >= H[i] ) { L[i] = L[L[i] - 1]; if ( L[i] == 1 ) break; } } //更新右边由n-1个开始,R[i]表示第i个矩形可以延伸的最右边的柱子 for ( int i = n - 1; i >= 1; i-- ) while ( H[R[i] + 1] >= H[i] ) { R[i] = R[R[i] + 1]; if ( R[i] == n ) break; } LL ans = -1; for ( int i = 1; i <= n; i++ ) { LL t = ( R[i] - L[i] + 1 ) * H[i]; if ( t > ans ) ans = t; } printf("%lld\n", ans); } return 0; }
1505
题目大意:给出一个n * m 的矩形,求全为F的矩形面积最大。
题目思路:这道题和HDU1506很像。
d[i][j]表示第i行j列元素在前i行中的最大高度。(以第一行为底)例如测试样例:
然后和HDU-1506思路一样,
找出以当前点位最低点能左右延伸的最长距离,也就是找出最左最右的下标,最后的 ans = max(num[i]*(r[i]-l[i]+1))
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL long long int const MAX = 1111; int const INF = 1 << 30; using namespace std; int mp[MAX][MAX], L[MAX], R[MAX], H[MAX][MAX]; int n, m; int main(int argc, char*argv[]) { int T; scanf("%d", &T); while ( T-- ) { scanf("%d%d", &n, &m); char s[3]; for ( int i = 1; i <= n; i++ ) for ( int j = 1; j <= m; j++ ) { scanf("%s", s); //F代表可用,设为1,方便计算高度 if ( s[0] == 'F' ) mp[i][j] = 1; else mp[i][j] = 0; } //计算每行点的高度和左右最长可延伸的位置,类似1506 for ( int i = 1; i <= n; i++ ) { //计算第i行第j列的高度 for ( int j = 1; j <= m; j++ ) { //如果不可用 if ( mp[i][j] == 0 ) H[i][j] = 0; //可以使用滚动数组 else H[i][j] = H[i - 1][j] + 1; } } /* for ( int i = 1; i <= n; i++ ) { for ( int j = 1; j <= m; j++ ) printf("%d ", H[i][j]); printf("\n"); } */ //对每一行使用1506的做法进行计算 int ans = -1; for ( int i = 1; i <= n; i++ ) { //计算左边 for ( int j = 1; j <= m; j++ ) L[j] = R[j] = j; for ( int j = 2; j <= m; j++ ) { while ( H[i][L[j] - 1] >= H[i][j] ) { L[j] = L[L[j] - 1]; if ( L[j] == 1 ) break; } } //计算右边 for ( int j = m - 1; j >= 1; j-- ) { while ( H[i][R[j] + 1] >= H[i][j] ) { R[j] = R[R[j] + 1]; if ( R[j] == m ) break; } 7fe8 } /* for ( int j = 1; j <= m; j++ ) printf("%d ", L[j]); printf("\n"); for ( int j = 1; j <= m; j++ ) printf("%d ", R[j]); printf("\n"); */ //计算总的 for ( int j = 1; j <= m; j++ ) { int t = ( R[j] - L[j] + 1 ) * H[i][j]; if ( t > ans ) ans = t; } } printf("%d\n", ans * 3); } return 0; }
2830
分析:扫描每一行,以该行作为底,用dp存放每一列1达到的高度,然后将高度排序(当然,不能直接对dp排序,因为扫下一行的有用),很容易就能找出最大的面积.最后就可以找出整体的最大值了
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL long long int const MAX = 1111; int const INF = 1 << 30; using namespace std; int mp[MAX][MAX], H[MAX][MAX], L[MAX], R[MAX]; int n, m; void show() { for ( int i = 1; i <= n; i++ ) { for ( int j = 1; j <= m; j++ ) printf("%d ", mp[i][j]); printf("\n"); } for ( int i = 1; i <= n; i++ ) { for ( int j = 1; j <= m; j++ ) printf("%d ", H[i][j]); printf("\n"); } } int main(int argc, char*argv[]) { while ( scanf("%d %d", &n, &m) == 2 ) { char s[1111]; for ( int i = 1; i <= n; i++ ) { scanf("%s", s + 1); for ( int j = 1; j <= m; j++ ) mp[i][j] = s[j] - '0'; } for ( int i = 1; i <= n; i++ ) for ( int j = 1; j <= m; j++ ) { if ( mp[i][j] == 1 ) H[i][j] = H[i - 1][j] + 1; else H[i][j] = 0; } // show(); //先按照高度排序,再对每一行使用1505的方法即可 int ans = -1; for ( int i = 1; i <= n; i++ ) { for ( int j = 1; j <= m; j++ ) L[j] = R[j] = j; sort(&H[i][1], &H[i][m] + 1); //计算左边 for ( int j = 2; j <= m; j++ ) { while ( H[i][L[j] - 1] >= H[i][j] ) { L[j] = L[L[j] - 1]; if ( L[j] == 1 ) break; } } //计算右边 for ( int j = m - 1; j >= 1; j-- ) { while ( H[i][R[j] + 1] >= H[i][j] ) { R[j] = R[R[j] + 1]; if ( R[j] == m ) break; } } //计算总和 for ( int j = 1; j <= m; j++ ) { int t = ( R[j] - L[j] + 1 ) * H[i][j]; ans = max(t, ans); } } printf("%d\n", ans); } return 0; }
2870
题意:一个由字符a,b,c,w,x,y,z组成的矩阵,其中w,x,y,z可以转换成a,b,c中的某几个字符,问该矩阵可以组成的由相同字符构成的最大子矩阵。
分析:DP。首先想到要求的子矩阵一定是由相同字符构成的,所以可以枚举w,x,y,z分别转换成a,b,c后得到的最大子矩阵即可。
枚举最大矩形是由哪个字母构成的
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL long long int const MAX = 1111; int const INF = 1 << 30; using namespace std; int n, m; char mp[MAX][MAX]; int H[MAX][MAX], L[MAX], R[MAX]; int ans = -1; //根据不同的字母计算出的H,计算最大值 void dp() { for ( int i = 1; i <= n; i++ ) { //计算左边 for ( int j = 1; j <= m; j++ ) L[j] = R[j] = j; for ( int j = 2; j <= m; j++ ) { while ( H[i][L[j] - 1] >= H[i][j] ) { L[j] = L[L[j] - 1]; if ( L[j] == 1 ) break; } } //计算右边 for ( int j = m - 1; j >= 1; j-- ) { while ( H[i][R[j] + 1] >= H[i][j] ) { R[j] = R[R[j] + 1]; if ( R[j] == m ) break; } } /* for ( int j = 1; j <= m; j++ ) printf("%d ", L[j]); printf("\n"); for ( int j = 1; j <= m; j++ ) printf("%d ", R[j]); printf("\n"); */ //计算总的 for ( int j = 1; j <= m; j++ ) { int t = ( R[j] - L[j] + 1 ) * H[i][j]; ans = max(ans, t); } } } int main(int argc, char*argv[]) { while ( scanf("%d %d", &n, &m) == 2 ) { ans = -1; for ( int i = 1; i <= n; i++ ) scanf("%s", mp[i] + 1); //由a构成 for ( int i = 1; i <= n; i++ ) { for ( int j = 1; j <= m; j++ ) { if ( mp[i][j] == 'a' || mp[i][j] == 'w' || mp[i][j] == 'y' || mp[i][j] == 'z' ) { H[i][j] = H[i - 1][j] + 1; } else { H[i][j] = 0; } } } dp(); for ( int i = 1; i <= n; i++ ) { for ( int j = 1; j <= m; j++ ) { if ( mp[i][j] == 'c' || mp[i][j] == 'x' || mp[i][j] == 'y' || mp[i][j] == 'z' ) { H[i][j] = H[i - 1][j] + 1; } else { H[i][j] = 0; } } } dp(); for ( int i = 1; i <= n; i++ ) { for ( int j = 1; j <= m; j++ ) { if ( mp[i][j] == 'b' || mp[i][j] == 'w' || mp[i][j] == 'x' || mp[i][j] == 'z' ) { H[i][j] = H[i - 1][j] + 1; } else { H[i][j] = 0; } } } dp(); printf("%d\n", ans); } return 0; }
相关文章推荐
- HDU 1505 1506 2830 2870求最大矩阵面积 DP
- HDU-1506 || HDU-1505 || HDU-2870 || HDU-2830
- hdu 1505 1506 2870 dp小礼包
- 动态规划求最大子矩阵详解(hdu 1505,1506 , 2870)
- hdu 1505 && hdu1506 &&hdu 2830 && 2870 总结---------DP之状图选最大矩形
- hdu 1506,1505,2870
- HDU 2870 最大子矩阵,联系1505, 1506
- hdu 1505 hdu 1506 hdu 2870 综合解答
- HDU 1506&1505 - Largest Rectangle in a Histogram & City Game
- hdu 1505,1506
- hdu 1505 city game (1506 加强版)
- hdu 1505 City Game 1506的二维
- HDU 1506 && HDU1505 && HDU 2870 (DP).
- HDU1505 1506升级版
- HDU 1505 Largest Rectangle in a Histogram && HDU 1506 City Game(动态规划)
- hdu 1505 1506的加强版
- HDU1505--City Game(动态规划)(1506加强版)
- hdu 1505 City Game (hdu 1506的升级版)
- 0和1中的最大子矩阵(1506加强版)(1505和2870)
- hdu 2870 1506增强版 求最大矩形