zoukankan      html  css  js  c++  java
  • uvalive 3029 City Game

    https://vjudge.net/problem/UVALive-3029

    题意:

    给出一个只含有F和R字母的矩阵,求出全部为F的面积最大的矩阵并且输出它的面积乘以3。

    思路:

    求面积最大的子矩阵,可以用扫描线。参考训练指南(orz,虽然并不知道为什么用扫描线)。

    对于每一个格子包含F,我们可以把它向上拉成一条悬线,直到上面的格子为R,然后观察这条悬线可以扫到左边与右边的最大距离,那么我们所求的面积就是所有的悬线中 悬线的长度乘以(右边界 - 左边界 + 1)的最大值。

    然后,需要计算悬线的长度,用up来表示,那么当这个格子为F时up(i,j) = up(i - 1,j) + 1(i >= 1),up(i,j) = 1,(i == 0);

    当这个格子为R时,up(i,j) = 0。

    然后,用left数组和right数组维护左右边界的信息:

    我们假设lo是当前格子之前的最近的是R的格子,从左往右遍历,那么 lo 的初值是-1,那么当(i,j) 为 F时 ,left(i,j) = max(left(i-1,j),lo + 1),为什么呢,因为当前的悬线如果是包含上一行此列的格子的话,那么就要考虑上一行左边的情况了;

    当(i,j)为R时,left(i,j) = 0。

    维护右边界的信息同理,不同的是求最小值和从右往左遍历。

    !!!:记住一边遍历,一边维护。输入也是坑!

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <algorithm>
      4 using namespace std;
      5 
      6 char a[1005][1005];
      7 int up[1005][1005],right[1005][1005],left[1005][1005];
      8 
      9 int main()
     10 {
     11     int t;
     12 
     13     scanf("%d",&t);
     14 
     15     while(t--)
     16     {
     17         int m,n;
     18 
     19         memset(a,0,sizeof(a));
     20         memset(up,0,sizeof(up));
     21         memset(right,0,sizeof(right));
     22         memset(left,0,sizeof(left));
     23 
     24         scanf("%d%d",&m,&n);
     25 
     26         getchar();
     27 
     28         for (int i = 0;i < m;i++)
     29             for (int j = 0;j < n;j++)
     30         {
     31             char s;
     32 
     33             s = getchar();
     34 
     35             while (s != 'R' && s != 'F') s = getchar();
     36 
     37             if (s == 'R') a[i][j] = 0;
     38             else a[i][j] = 1;
     39         }
     40 
     41         /*for (int i= 0;i < m;i++)
     42         {
     43             for (int j = 0;j < n;j++) printf("%d",(int)a[i][j]);
     44 
     45             printf("
    ");
     46         }*/
     47 
     48         int ans = 0;
     49 
     50         for (int i = 0;i < m;i++)
     51         {
     52             for (int j = 0;j < n;j++)
     53             {
     54                 if (i == 0)
     55                 {
     56                     up[i][j] = a[i][j];
     57                 }
     58                 else
     59                 {
     60                     if (a[i][j]) up[i][j] = up[i-1][j] + 1;
     61                     else up[i][j] = 0;
     62                 }
     63             }
     64 
     65             int lo = -1,ro = n;
     66 
     67             if (i == 0)
     68             {
     69                 for (int j = 0;j < n;j++)
     70                 {
     71                     if (a[i][j] == 0) left[i][j] = 0, lo = j;
     72                     else left[i][j] = lo + 1;
     73                 }
     74 
     75                 for (int j = n - 1;j >= 0;j--)
     76                 {
     77                     if (a[i][j] == 0) right[i][j] = n, ro = j;
     78                     else right[i][j] = ro - 1;
     79                 }
     80 
     81                 for (int j = 0;j < n;j++)
     82                 {
     83                     int tmp = up[i][j] * (right[i][j] - left[i][j] + 1);
     84 
     85                     ans = max(ans,tmp * 3);
     86                 }
     87             }
     88             else
     89             {
     90                 for (int j = 0;j < n;j++)
     91                 {
     92                     if (a[i][j] == 0) left[i][j] = 0, lo = j;
     93                     else left[i][j] = max(lo + 1,left[i-1][j]);
     94                 }
     95 
     96                 for (int j = n - 1;j >= 0;j--)
     97                 {
     98                     if (a[i][j] == 0) right[i][j] = n, ro = j;
     99                     else right[i][j] = min(ro - 1,right[i-1][j]);
    100                 }
    101 
    102                 for (int j = 0;j < n;j++)
    103                 {
    104                     int tmp = up[i][j] * (right[i][j] - left[i][j] + 1);
    105 
    106                     ans = max(ans,tmp * 3);
    107                 }
    108             }
    109         }
    110 
    111         /*for (int i = 0;i < m;i++)
    112         {
    113             for (int j = 0;j < n;j++)
    114             {
    115                 printf("%d %d %d
    ",up[i][j],left[i][j],right[i][j]);
    116             }
    117         }*/
    118 
    119         printf("%d
    ",ans);
    120     }
    121 
    122     return 0;
    123 }
  • 相关阅读:
    新数学丛书《连分数》 习题 1.1
    连分数中一个有意思的小玩意儿
    无聊博文之:用同余的语言阐述欧几里德算法
    有向无环图
    Codeforces Round #658 (Div. 2)
    常用代码模板3——搜索与图论
    什么是动态规划?动态规划的意义是什么?(转自知乎)
    Codeforce:4C. Registration system (映射)
    C++与正则表达式入门
    常用代码模板4——数学知识
  • 原文地址:https://www.cnblogs.com/kickit/p/7623700.html
Copyright © 2011-2022 走看看