码迷,mamicode.com
首页 > 其他好文 > 详细

hdu--1505--稍微特别的子矩阵求和

时间:2014-08-05 18:40:49      阅读:256      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   使用   os   io   数据   

这题 是蛮特别的..

虽然可以将R F转换为 0 1然后求最大子矩阵和 但是这个矩阵中 不能有0 即这个矩阵的元素都是1即F

这题 一开始不会做啊=-= 看了discuss里面的人用了 left 和 right数组 还是一知半解 白痴啊=-=

我把我的理解和porker讲了下 他纠正了我的错误... ------touch  me

我这边将left 和 next 和 height数组简单讲下我的理解 因为我发现 基本上所有人都是没有给出解释的。。。

假如我们现在要操作第 X 行 的 第 Y 列 那么 left[ Y ]就是在Y列左边 能取到的最小列的编号Z使得从Z到Y的列的height都是>=Y

那么right[ Y ]就是同理了 一个是在右边 一个是在左边罢了

height[ Y ]就是在第X行时 第Y列及上门1-X行包含第Y列的连续free space有几个 这边当时有个情况一下子没理解 假如第X行的情况是 F R F F R F那么它对应的height[]值就是1 0 1 2 0 1因为如果是R 就会判断将height[ Y ]重置为0

那么 一个包含第 Y 列的矩阵的面积就是 height[ Y ] * ( RIGHT[ Y ] - LEFT[ Y ] + 1 )

这题 的核心代码 我觉得应该就是---前面一个对于 h l r三个数组的预处理

1 memset( height , 0 , sizeof(height) );
2 for( int i = 1 ; i<=m ; i++ )
3 {
4     Left[i] = i;
5     Right[i] = i;
6 }

 

 1 for( int k = 2 ; k<=m ; k++ )  
 2 {
 3     if( h[ Left[k]-1 ] >= h[k] )//其实 完全可以写成  if( h[ k-1 ] >= h[ k ] ){ left[ k ] = left[ k-1 ] ;;关于right数组 下同 至于代码那边就懒得去改了
 4     {
 5         Left[k] = Left[ Left[k]-1 ];
 6     }
 7 }
 8 
 9 for( int q = m-1 ; q>=1 ; q-- )  
10 {
11     if( h[ Right[q]+1 ] >= h[q] )
12     {
13         Right[q] = Right[ Right[q]+1 ];
14     }
15 }

 

我发现 很多人对于这个left right数组进行求解的时候 都是while循环 就像下面这样

 1 h[0] = h[m+1] = -1;
 2 
 3 for( int k = 2 ; k<=m ; k++ )  
 4 {
 5     while( h[ Left[k]-1 ] >= h[k] )
 6     {
 7         Left[k] = Left[ Left[k]-1 ];
 8     }
 9 }
10 
11 for( int q = m-1 ; q>=1 ; q-- )  
12 {
13     while( h[ Right[q]+1 ] >= h[q] )
14     {
15         Right[q] = Right[ Right[q]+1 ];
16     }
17 }

如果你是用while循环 那么一定不能忘了这个边界处理 h[0] h[m+1] 因为循环可能会存在情况到边界判断

但其实完全没必要的 因为我们的left right数组在计算的时候 我们都运用了前面计算得到的结果 直接会跳转到最终的情况、

-----------------------------

上面是O(n*m)的解法 当然 更普通的解法是O(n^3)的解法 我在1081里就是这样做的 但是当时的数据是只有100  而这里是1000

porker提醒我的用这个方法解下看  我自己当时因为觉得O(n^3)怎么判断这个和最大的矩阵不含有Ri呢?  其实很简单 只要将每个R出现的地方 都设一个负值 使如果含有该R的子矩阵的和都是负数 就可以了   这里的负值 不能设太小 因为这样可能会存在数值溢出 因为如果使用64位int计算的话 速度会更慢一些 相比于使用32位int 这里已经存在tle的风险了 尽量节约时间

but -------------还是 tle了 =-=  谁看到这边 如果使用了我这种思想AC的 不妨留下你的评论与方法。。

--------更加难想到的是用stack维护一个单调窗口吧  我还没很好掌握它 先不说了

 

bubuko.com,布布扣
 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 const int inf = -1100000;
 6 const int size = 1010;
 7 int matrix[size][size];
 8 
 9 int main()
10 {
11     cin.sync_with_stdio(false);
12     int n , m , t , ans , sum , temp , num;
13     char ch;
14     while( cin >> t )
15     {
16         while( t-- )
17         {
18             ans = 0;
19             cin >> n >> m;
20             memset( matrix , 0 , (n+3)*(m+3)*sizeof(int) );
21             for( int i = 1 ; i<=n ; i++ )
22             {
23                 for( int j = 1 ; j<=m ; j++ )
24                 {
25                     cin >> ch;
26                     if( ch==F )
27                         num = 1;
28                     else
29                         num = inf;
30                     matrix[i][j] = matrix[i-1][j] + num;
31                 }
32             }
33             for( int i = 1 ; i<=n ; i++ )
34             {
35                 for( int j = i ; j<=n ; j++ )
36                 {
37                     sum = 0;
38                     for( int k = 1 ; k<=m ; k++ )
39                     {
40                         temp = matrix[j][k] - matrix[i-1][k];
41                         sum += temp;
42                         if( sum>ans )
43                             ans = sum;
44                         if( sum<0 )
45                             sum = 0;
46                     }
47                 }
48             }
49             cout << 3*ans << endl;
50         }
51     }
52     return 0;
53 }
View Code

 

bubuko.com,布布扣
 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int size = 1010;
 7 int Left[size];
 8 int Right[size];
 9 int h[size];
10 
11 int main()
12 {
13     cin.sync_with_stdio(false);
14     int n , m , t , ans;
15     char ch;
16     while( cin>>t )
17     {
18         while( t-- )
19         {
20             memset( h , 0 , sizeof(h) );
21             ans = 0;
22             cin >> n >> m;
23             for( int i = 1 ; i<=n ; i++ )
24             {
25                 for( int j = 1 ; j<=m ; j++ )
26                 {
27                     cin >> ch;
28                     if( ch ==F )
29                         h[j] ++;
30                     else
31                         h[j] = 0;
32                     Left[j] = Right[j] = j;
33                 }
34                 //h[0] = h[m+1] = -1;
35                 for( int k = 2 ; k<=m ; k++ )  
36                 {
37                     if( h[ Left[k]-1 ] >= h[k] )
38                     {
39                         Left[k] = Left[ Left[k]-1 ];
40                     }
41                 }
42                 for( int q = m-1 ; q>=1 ; q-- )  
43                 {
44                     if( h[ Right[q]+1 ] >= h[q] )
45                     {
46                         Right[q] = Right[ Right[q]+1 ];
47                     }
48                 }
49                 for( int r = 1 ; r<=m ; r++ )
50                 {
51                     ans = max( ans , h[r] * ( Right[r] - Left[r] + 1 ) );
52                 }
53             }
54             cout << 3*ans << endl;
55         }
56     }
57     return 0;
58 }
View Code

 

today:

  crave you name on hearts and not on marbles

 

hdu--1505--稍微特别的子矩阵求和,布布扣,bubuko.com

hdu--1505--稍微特别的子矩阵求和

标签:style   blog   http   color   使用   os   io   数据   

原文地址:http://www.cnblogs.com/radical/p/3892597.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!