动态规划求最大子矩阵详解(hdu 1505,1506 , 2870)
来源:互联网 发布:提高淘宝店铺关注率 编辑:程序博客网 时间:2024/06/08 14:13
动态规划求最大子矩阵
对于hdu 1505,1506,都是求关于最大子矩阵的问题,因为n为1000,n^3必然超时,因此需要优化,这类题应用了一种特殊的优化算法使时间复杂度降到了n*n。
优化算法
因为求最大子矩阵,都需要求最左边比该点高的位置,最右边比该点高的位置。因此就先假如我们现在我们求l[n],很明显现在l[1……n-1]都已经求出来了,那么我们就可以利用前面求得的对其进行优化,同理求r[n]。
优化的代码:
l[1] = 1;
for(int i = 2; i <= n; i++)
{
int t = i;
while(t > 1 && h[t-1] >= h[i])
t = l[t-1];
l[i] = t;
}
r[n] = n;
for(int i = n-1; i >= 1; i–)
{
int t = i;
while(t < n && h[t+1] >= h[i])
t = r[t+1];
r[i] = t;
}
因此1506题就可以得出,代码为:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const int maxn = 100005;LL l[maxn],r[maxn],h[maxn];int main(){ int n; while(scanf("%d", &n) != EOF && n) { for(int i = 1; i <= n; i++) scanf("%I64d", &h[i]); l[1] = 1; for(int i = 2; i <= n; i++) { int t = i; while(t > 1 && h[t-1] >= h[i]) t = l[t-1]; l[i] = t; } r[n] = n; for(int i = n-1; i >= 1; i--) { int t = i; while(t < n && h[t+1] >= h[i]) t = r[t+1]; r[i] = t; } LL ans = 0; for(int i = 1; i <= n; i++) ans = max(ans, h[i]*(r[i]-l[i]+1)); printf("%I64d\n", ans); } return 0;}
对于1505则需要转化一下:对于F(空闲区),我们将该值设置为dp[i][j] = dp[i-1][j] +1;对于R直接设置为0即可。举个例子:
R F F R
F F F F
F F F R
R F F F0 1 1 0
1 2 2 1
2 3 3 0
0 4 4 1
这样同样可以用1506题的解法解决这一问题,AC代码为:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1005;int dp[maxn][maxn];int l[maxn],r[maxn];int main(){ char s[2]; int T,n,m; scanf("%d", &T); while(T--) { scanf("%d %d", &n, &m); memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { scanf("%s", s); if(s[0] == 'F') dp[i][j] = dp[i-1][j] + 1; else dp[i][j] = 0; } } int ans = 0; for(int i = 1; i <= n; i++) { l[1] = 1; for(int j = 2; j <= m; j++) { int t = j; while(t > 1 && dp[i][t-1] >= dp[i][j]) t = l[t-1]; l[j] = t; } r[m] = m; for(int j = m-1; j >= 1; j--) { int t = j; while(t < m && dp[i][t+1] >= dp[i][j]) t = r[t+1]; r[j] = t; } for(int j = 1; j <= m; j++) ans = max(ans, (r[j]-l[j]+1)*dp[i][j]); } printf("%d\n", ans*3); } return 0;}
对于2870题,很明显也是求最大子矩阵问题,但是这里面有3种字母,很明显将别的字母统一转化a,b,c即可求出,剩余就和1505题一样了。给出AC代码:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1005;char s[maxn][maxn];int dp[maxn][maxn],l[maxn],r[maxn];int main(){ int n,m; while(scanf("%d %d", &n, &m) != EOF) { for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1); int ans = 0; memset(dp,0,sizeof(dp)); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) if(s[i][j] == 'a' || s[i][j] == 'w' || s[i][j] == 'y' || s[i][j] == 'z') dp[i][j] = dp[i-1][j] + 1; else dp[i][j] = 0; for(int i = 1; i <= n; i++) { l[1] = 1; for(int j = 2; j <= m; j++) { int t = j; while(t > 1 && dp[i][t-1] >= dp[i][j]) t = l[t-1]; l[j] = t; } r[m] = m; for(int j = m-1; j >= 1; j--) { int t = j; while(t < m && dp[i][t+1] >= dp[i][j]) t = r[t+1]; r[j] = t; } for(int j = 1; j <= m; j++) ans = max(ans, (r[j]-l[j]+1)*dp[i][j]); } memset(dp,0,sizeof(dp)); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) if(s[i][j] == 'b' || s[i][j] == 'w' || s[i][j] == 'x' || s[i][j] == 'z') dp[i][j] = dp[i-1][j] + 1; else dp[i][j] = 0; for(int i = 1; i <= n; i++) { l[1] = 1; for(int j = 2; j <= m; j++) { int t = j; while(t > 1 && dp[i][t-1] >= dp[i][j]) t = l[t-1]; l[j] = t; } r[m] = m; for(int j = m-1; j >= 1; j--) { int t = j; while(t < m && dp[i][t+1] >= dp[i][j]) t = r[t+1]; r[j] = t; } for(int j = 1; j <= m; j++) ans = max(ans, (r[j]-l[j]+1)*dp[i][j]); } memset(dp,0,sizeof(dp)); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) if(s[i][j] == 'c' || s[i][j] == 'x' || s[i][j] == 'y' || s[i][j] == 'z') dp[i][j] = dp[i-1][j] + 1; else dp[i][j] = 0; for(int i = 1; i <= n; i++) { l[1] = 1; for(int j = 2; j <= m; j++) { int t = j; while(t > 1 && dp[i][t-1] >= dp[i][j]) t = l[t-1]; l[j] = t; } r[m] = m; for(int j = m-1; j >= 1; j--) { int t = j; while(t < m && dp[i][t+1] >= dp[i][j]) t = r[t+1]; r[j] = t; } for(int j = 1; j <= m; j++) ans = max(ans, (r[j]-l[j]+1)*dp[i][j]); } printf("%d\n", ans); } return 0;}
- 动态规划求最大子矩阵详解(hdu 1505,1506 , 2870)
- HDU 2870(动态规划-最大子矩阵)
- HDU 1505(动态规划-最大子矩阵)
- HDU:1559 最大子矩阵(动态规划DP)
- 【动态规划】求二维矩阵的最大和子矩阵
- HDOJ To The Max 1081【动态规划-详解求最大子矩阵】
- 最大子矩阵(动态规划)
- 动态规划 02 (最大子矩阵)
- 最大子矩阵(动态规划)
- 【BZOJ1084】最大子矩阵(动态规划)
- POJ 1050 求最大子矩阵和 动态规划
- 动态规划之求最大子矩阵问题
- 动态规划 最大子矩阵
- 【动态规划】最大子矩阵
- 动态规划-最大子矩阵
- 动态规划:最大子矩阵
- 动态规划 最大子矩阵
- 动态规划----最大子矩阵
- NodeJS学习历程(3)
- 一遍成功安装"Cocoapods"
- hdu 4001 To Miss Our Children Time
- linux learning notes:1.filesystem and mount point
- Gbrbow算法 强连通分量 --有向图
- 动态规划求最大子矩阵详解(hdu 1505,1506 , 2870)
- 详解spring事务属性
- 通过NSURLProtocol来做UIWebView的cache
- java 打印程序运行时间
- javaee-SpringFramework下载
- 数据结构复习 - 栈Stack
- java知识点
- 基于U-BOOT-2010.09移植OK6410开发版记录(三)
- 有关网络协议融合、存储关键知识点的一些理解