zoukankan      html  css  js  c++  java
  • BZOJ 1201 [HNOI2005]数三角形:枚举 + 前缀和

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1201

    题意:

      有一个边长为n的正三角形网格,去掉其中一些线段,问你在这幅图中有多少个三角形。

     

    题解:

      枚举 + 前缀和。

     

      三角形总共有两种:正着放的、倒着放的。

      分别处理就好。

      总复杂度 < O(N^3)

     

      为了判断某一个三角形是否存在,需要迅速判断它的三边是否都是实线(不断开)。

      所以建立三个前缀和,分别代表左、右、底边在对应方向上的边长和。

      若某一边上的区间和[a,b] == b-a+1,则为实线。

      如图为前缀和方向:

      

     

     

      正着放的:

        N^2枚举三角形最顶上的小三角形,再套一个for枚举向下延伸的边长k。

      

     

      倒着放的:

        倒三角形底部有一个小倒三角形,枚举它左边相邻的小正三角。

      

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #define MAX_N 1005
     5 
     6 using namespace std;
     7 
     8 int n;
     9 int ans=0;
    10 int l[MAX_N][MAX_N];
    11 int r[MAX_N][MAX_N];
    12 int b[MAX_N][MAX_N];
    13 int lef[MAX_N][MAX_N];
    14 int rig[MAX_N][MAX_N];
    15 int btm[MAX_N][MAX_N];
    16 
    17 void read()
    18 {
    19     memset(l,0,sizeof(l));
    20     memset(r,0,sizeof(r));
    21     memset(b,0,sizeof(b));
    22     cin>>n;
    23     for(int i=1;i<=n;i++)
    24     {
    25         for(int j=1;j<=i;j++)
    26         {
    27             cin>>l[i][j]>>r[i][j]>>b[i][j];
    28         }
    29     }
    30 }
    31 
    32 void cal_sum()
    33 {
    34     memset(lef,0,sizeof(lef));
    35     memset(rig,0,sizeof(rig));
    36     memset(btm,0,sizeof(btm));
    37     for(int i=1;i<=n;i++)
    38     {
    39         for(int j=1;j<=i;j++)
    40         {
    41             lef[i][j]=lef[i-1][j]+l[i][j];
    42             rig[i][j]=rig[i-1][j-1]+r[i][j];
    43             btm[i][j]=btm[i][j-1]+b[i][j];
    44         }
    45     }
    46 }
    47 
    48 void find_tri()
    49 {
    50     for(int i=1;i<=n;i++)
    51     {
    52         for(int j=1;j<=i;j++)
    53         {
    54             for(int k=1;;k++)
    55             {
    56                 if(lef[i+k-1][j]-lef[i-1][j]<k) break;
    57                 if(rig[i+k-1][j+k-1]-rig[i-1][j-1]<k) break;
    58                 if(btm[i+k-1][j+k-1]-btm[i+k-1][j-1]<k) continue;
    59                 ans++;
    60             }
    61         }
    62     }
    63     for(int i=1;i<=n;i++)
    64     {
    65         for(int j=1;j<i;j++)
    66         {
    67             for(int k=1;i-k>=0 && j-k>=0;k++)
    68             {
    69                 if(lef[i][j+1]-lef[i-k][j+1]<k) break;
    70                 if(rig[i][j]-rig[i-k][j-k]<k) break;
    71                 if(btm[i-k][j]-btm[i-k][j-k]<k) continue;
    72                 ans++;
    73             }
    74         }
    75     }
    76 }
    77 
    78 void solve()
    79 {
    80     cal_sum();
    81     find_tri();
    82 }
    83 
    84 void print()
    85 {
    86     cout<<ans<<endl;
    87 }
    88 
    89 int main()
    90 {
    91     read();
    92     solve();
    93     print();
    94 }
  • 相关阅读:
    fiber
    ACM用到的算法。先做个笔记,记一下
    matlab安装及破解
    银行家算法
    网络安全(超级详细)零基础带你一步一步走进缓冲区溢出漏洞和shellcode编写!
    心脏滴血漏洞复现(CVE-2014-0160)
    KMP算法分析
    利用BURPSUITE检测CSRF漏洞
    BURPSUITE爆破密码
    动态规划—最长回文子串LEETCODE第5题深度剖析
  • 原文地址:https://www.cnblogs.com/Leohh/p/7518577.html
Copyright © 2011-2022 走看看