uva 10755 Garbage Heap

https://vjudge.net/problem/UVA-10755

题意:

给出一个长方体,叫你求哪个子矩阵的和最大,输出的是最大值。

思路:

首先,n的规模是20,那么最常规的算法,枚举起点,枚举终点,之后循环计算,那么这个的复杂度就是O(N^9)。

这个想法其实是比较自然的,那么可以加一些优化进去,减小复杂度。

首先,三维的问题,可以通过降维解决,枚举竖坐标,降成一维解决。

降成一维之后,如果还是枚举起点与终点,那么复杂度还是高达O(N^8)。

那么其实坐标平面的问题可以用前缀和来优化,所以再用上前缀和优化。

之后,最大子矩阵就可以用动态规划解决了。

tmp = sum[i][j] - sum[k-1][j],这里的sum记录的是降维之后的前缀和,然后k从1到x枚举,i从k到x枚举,j从1到y枚举,

这个操作把一个矩阵变成了一条线,于是就用最大连续和的思想解决。

总的复杂度是O(N^5)。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 long long a[25][25][25];
 7 
 8 long long b[25][25];
 9 long long sum[25][25];
10 
11 int main()
12 {
13     int t;
14 
15     scanf("%d",&t);
16 
17     while (t--)
18     {
19         long long ans = -1e18;
20 
21         int x,y,z;
22 
23         scanf("%d%d%d",&x,&y,&z);
24 
25         for (int i = 1;i <= x;i++)
26             for (int j = 1;j <= y;j++)
27             for (int k = 1;k <= z;k++)
28             scanf("%lld",&a[i][j][k]);
29 
30         for (int i = 1;i <= z;i++)
31             for (int j = i;j <= z;j++)
32         {
33             memset(b,0,sizeof(b));
34 
35             for (int k = i;k <= j;k++)
36             {
37                 for (int m = 1;m <= x;m++)
38                     for (int n = 1;n <= y;n++)
39                     b[m][n] += a[m][n][k];
40             }
41 
42             memset(sum,0,sizeof(sum));
43 
44             for (int m = 1;m <= x;m++)
45                 for (int n = 1;n <= y;n++)
46             {
47                 sum[m][n] = sum[m-1][n] + sum[m][n-1] - sum[m-1][n-1] + b[m][n];
48             }
49 
50             for (int m = 1;m <= x;m++)
51                 for (int n = m;n <= x;n++)
52             {
53                 long long orz = 0;
54 
55                 for (int k = 1;k <= y;k++)
56                 {
57                     long long tmp = sum[n][k] - sum[m-1][k];
58 
59                     ans = max(ans,tmp - orz);
60 
61                     orz = min(tmp,orz);
62                 }
63             }
64         }
65 
66         printf("%lld\n",ans);
67 
68         if (t) printf("\n");
69     }
70 
71     return 0;
72 }

 

posted @ 2017-10-11 15:26  qrfkickit  阅读(193)  评论(0编辑  收藏  举报