zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    NGUI_Depth
    NGUI_Font
    NGUI_Atlas
    NGUI_概述
    02、Mecanim之IK动画
    JAVA8学习——深入Comparator&Collector(学习过程)
    JAVA8学习——从源码角度深入Stream流(学习过程)
    JAVA8学习——从使用角度深入Stream流(学习过程)
    JAVA8学习——深入浅出方法引用(学习过程)
    回顾2019,总结,反思,展望,行动。
  • 原文地址:https://www.cnblogs.com/Griselda/p/3067655.html
Copyright © 2011-2022 走看看