

1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 6 #define gmax(a,b) ((a)>(b)?(a):(b)) 7 #define fill(a,b) memset(a,b,sizeof(a)) 8 #define MAXN 2000 9 #define MAXM 2000 10 11 using namespace std; 12 13 int n, m, k; 14 int a[MAXN][MAXM]; 15 int s[MAXN][MAXM]; 16 int ak[MAXN][MAXM]; 17 int lu[MAXN][MAXM], ru[MAXN][MAXM], ld[MAXN][MAXM], rd[MAXN][MAXM]; 18 int ans; 19 20 int main(){ 21 22 freopen("oil.in", "r", stdin); 23 freopen("oil.out", "w", stdout); 24 25 int i, j; 26 scanf("%d %d %d", &n, &m, &k); 27 for (i=1; i<n+1; i++){ 28 for (j=1; j<m+1; j++){ 29 scanf("%d", &a[i][j]); 30 } 31 } 32 // 33 fill(s, 0); 34 for (i=1; i<n+1; i++){ 35 for (j=1; j<m+1; j++){ 36 s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j]; 37 } 38 } 39 // 40 fill(ak, 0); 41 for (i=k; i<n+1; i++){ 42 for (j=k; j<m+1; j++){ 43 ak[i][j] = s[i][j] - s[i - k][j] - s[i][j - k] + s[i - k][j - k]; 44 } 45 } 46 // 47 fill(lu, 0); 48 for (i=k; i<n+1; i++){ 49 for (j=k; j<m+1; j++){ 50 lu[i][j] = ak[i][j]; 51 lu[i][j] = gmax(lu[i][j], lu[i - 1][j]); 52 lu[i][j] = gmax(lu[i][j], lu[i][j - 1]); 53 } 54 } 55 // 56 fill(ru, 0); 57 for (i=k; i<n+1; i++){ 58 for (j=m-k+1; j; j--){ 59 ru[i][j] = ak[i][j + k - 1]; 60 ru[i][j] = gmax(ru[i][j], ru[i - 1][j]); 61 ru[i][j] = gmax(ru[i][j], ru[i][j + 1]); 62 } 63 } 64 // 65 fill(ld, 0); 66 for (i=n-k+1; i; i--){ 67 for (j=k; j<m+1; j++){ 68 ld[i][j] = ak[i + k - 1][j]; 69 ld[i][j] = gmax(ld[i][j], ld[i + 1][j]); 70 ld[i][j] = gmax(ld[i][j], ld[i][j - 1]); 71 } 72 } 73 // 74 fill(rd, 0); 75 for (i=n-k+1; i; i--){ 76 for (j=m-k+1; j; j--){ 77 rd[i][j] = ak[i + k - 1][j + k - 1]; 78 rd[i][j] = gmax(rd[i][j], rd[i + 1][j]); 79 rd[i][j] = gmax(rd[i][j], rd[i][j + 1]); 80 } 81 } 82 // 83 ans = 0; 84 // 85 //1|1|1 86 // 87 for (j=k; j+(k<<1)<m+1; j++){ 88 for (i=k; i<n+1; i++){ 89 int t = lu[n][j] + ak[i][j + k] + ru[n][j + k + 1]; 90 ans = gmax(ans, t); 91 } 92 } 93 // 94 //1 95 //1 96 //1 97 for (i=k; i+(k<<1)<n+1; i++){ 98 for (j=k; j<m+1; j++){ 99 int t = lu[i][m] + ak[i + k][j] + ld[i + k + 1][m]; 100 ans = gmax(ans, t); 101 } 102 } 103 // 104 // 1 105 //1| 106 // 1 107 for (j=k; j+k<m+1; j++){ 108 for (i=k; i+k<n+1; i++){ 109 int t = lu[n][j] + ru[i][j + 1] + rd[i + 1][j + 1]; 110 ans = gmax(ans, t); 111 } 112 } 113 // 114 //1 115 // |1 116 //1 117 for (j=k; j+k<m+1; j++){ 118 for (i=k; i+k<n+1; i++){ 119 int t = lu[i][j] + ld[i + 1][j] + rd[1][j + 1]; 120 ans = gmax(ans, t); 121 } 122 } 123 // 124 // 1 125 //1 1 126 for (i=k; i+k<n+1; i++){ 127 for (j=k; j+k<m+1; j++){ 128 int t = lu[i][n] + ld[i + 1][j] + rd[i + 1][j + 1]; 129 ans = gmax(ans, t); 130 } 131 } 132 // 133 //1 1 134 // 1 135 for (i=k; i+k<n+1; i++){ 136 for (j=k; j+k<m+1; j++){ 137 int t = lu[i][j] + ru[i][j + 1] + ld[i + 1][m]; 138 ans = gmax(ans, t); 139 } 140 } 141 142 143 printf("%d\n", ans); 144 145 fclose(stdin); 146 fclose(stdout); 147 148 return 0; 149
主要思想就是,
肯定要预处理出来矩阵前缀和
s[i][j]代表1..i行1..j列数字之和。
然后处理出以(i,j)为右下角的k*k的矩阵元素之和。
然后分别处理出以(i,j)为左上角,左下角,右上角,右下角的最大矩阵中最大的k*k的值。
然后分6中情况讨论(每种情况都是2层循环,所以总复杂度是O(n^2)的)
今天评测时发现速度不太快,好几个1s多,但是对于官方要求的1.5s还是AC了。