题意:
给出一个n*n的矩阵和m个数,从m个数中选几个数填入矩阵中值为0的空格中,使矩阵的和最大。
矩阵的和的定义是:所有子矩阵的数的和的和..
思路:
要想矩阵的和最大..应该使m个数中值大的数填入矩阵中出现次数多的0格中..
所有其实可以看做是求解矩阵中每一个0格被子矩阵包含的次数..
以前做过一道题是一维的成段更新..方法是:http://www.cnblogs.com/Griselda/archive/2012/09/15/2686074.html
这道题类似..就是譬如要更新(x, y)到(x+k, y+k)的二维矩阵..
就在(x, y)处设为1,在(x+k+1, y+k+1)处设为1
在(x, y+1)和(x+1, y)处设为-1..
然后求(x0, y0)的被包含次数就累计从(0, 0)到该点的和..
Tips:
答案要用long long 存..
计算每一个0格的和的时候..
我一开始用暴力的方法..跑了140ms..
后来优化了一下..跑了97ms~优化的方法就是用从sum[i-1][j]的值加上t_sum[i][0~j]..
Code:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <stdio.h> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 const int N = 35; 8 const int M = 100010; 9 10 int cmp(int a, int b) 11 { 12 return a>b; 13 } 14 15 int arr[N][N], ar[M], t_arr[N][N], ans[N][N], t_ans[N*N]; 16 bool is_zero[N][N]; 17 18 int main() 19 { 20 // freopen("in.txt", "r", stdin); 21 int T, n, m, k; 22 int cnt, s; 23 long long sum; 24 scanf("%d", &T); 25 while (T--) { 26 memset(t_arr, 0, sizeof(t_arr)); 27 memset(ans, 0, sizeof(ans)); 28 memset(is_zero, 0, sizeof(is_zero)); 29 k = cnt = sum = 0; 30 scanf("%d", &n); 31 for (int i = 0; i < n; ++i) 32 for (int j = 0; j < n; ++j) { 33 scanf("%d", &arr[i][j]); 34 if (arr[i][j] == 0) { 35 k++; 36 is_zero[i][j] = true; 37 } 38 } 39 scanf("%d", &m); 40 for (int i = 0; i < m; ++i) 41 scanf("%d", &ar[i]); 42 43 for (int i = 0; i < n; ++i) 44 for (int j = 0; j < n; ++j) { 45 for (int k = 1; max(i, j)+k <= n; ++k) { 46 t_arr[i][j]++; 47 t_arr[i+k][j+k]++; 48 t_arr[i][j+k]--, t_arr[i+k][j]--; 49 } 50 } 51 52 for (int i = 0; i < n; ++i) { 53 s = 0; 54 for (int j = 0; j < n; ++j) { 55 s += t_arr[i][j]; 56 ans[i][j] = ans[i-1][j]+s; 57 if (is_zero[i][j]) t_ans[cnt++] = ans[i][j]; 58 } 59 } 60 /* 61 for (int i = 0; i < n; ++i) 62 for (int j = 0; j < n; ++j) 63 if (is_zero[i][j]) { 64 for (int ii = 0; ii <= i; ++ii) 65 for (int jj = 0; jj <= j; ++jj) 66 ans[i][j] += t_arr[ii][jj]; 67 t_ans[cnt++] = ans[i][j]; 68 } 69 */ 70 sort(ar, ar+m, cmp); 71 sort(t_ans, t_ans+cnt, cmp); 72 73 for (int i = 0; i < k; ++i) 74 sum += ar[i]*t_ans[i]; 75 76 77 printf("%I64d\n", sum); 78 79 } 80 return 0; 81 }