Hdu 1794 【二维成段更新】.cpp

题意:

  给出一个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:

  

View Code
 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 }

 

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1794

posted @ 2013-05-08 20:15  Griselda.  阅读(265)  评论(0编辑  收藏  举报