• Spotlights【思维+前缀和优化】


    https://blog.csdn.net/mengxiang000000/article/details/53291883   原博客地址

    http://codeforces.com/group/1EzrFFyOc0/contest/738/problem/B  题目链接

    题目大意:

    给你一个N*M的空间,其中0表示没有人,1表示有人,对应一个好位子以及方向的定义为:

    ①首先这个位子不能有人。

    ②其次对应这个位子安排一个照明方向,这个方向上必须有人才行。

    让你求一共有多少个这样满足的放置方案。

    思路:

     

    1、首先我们O(n*m)暴力枚举出所有的没有人的位子。然后我们如果暴力判断其一行一列的四个方向是否有人的话,时间复杂度会高达:O(n^3)【我们若视n==m的情况下】显然会TLE。

     

    2、那么我们考虑优化:

    ①设定sum【i】【j】表示第i行,从第一个数加到第j个数的和(前缀和),那么如果我们此时保证(i,j)是没有人的,并且sum【i】【j】>0,那么说明位子(i,j)的左侧有人,那么对应这个位子放置照明方向为左,即是一个可行解。那么同理,如果sum【i】【m】-sum【i】【j】>0,那么说明位子(i,j)的右侧有人,那么对应这个位子放置照明方向为右,即也是一个可行解。

    ②同理,再设定sum2【i】【j】表示第j列,从第一个数加到第i个数的和,那么同理,如果我们此时保证(i,j)是没有人的,并且sum2【i】【j】>0,那么说明位子(i,j)的上边有人,那么对应这个位子放置照明方向为上,即是一个可行解。那么也是同理,如果sum2【n】【j】-sum2【i】【j】>0,那么说明位子(i,j)的下边有人,那么对应这个位子放置照明方向为下,即也是一个可行解。

    ③那么此时我们暴力枚举出没有人的位子之后,只需要常数级的操作既可以搞定这个问题了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<set>
     7 #include<vector>
     8 #include<stack>
     9 #include<queue>
    10 #include<map>
    11 using namespace std;
    12 #define ll long long
    13 #define se second
    14 #define fi first
    15 const int Mos = 0x7FFFFFFF;  //2147483647
    16 const int nMos = 0x80000000;  //-2147483648
    17 const int maxn=1e6+5;
    18 
    19 int mp[1005][1005];
    20 int sum1[1005][1005],sum2[1005][1005];
    21 int n,m,cnt=0;
    22 
    23 int main()
    24 {
    25     cin>>n>>m;
    26     for(int i=1;i<=n;i++)
    27         for(int j=1;j<=m;j++)
    28         {
    29             scanf("%d",&mp[i][j]);
    30             sum1[i][j]=mp[i][j]+sum1[i][j-1]; //左到右累加
    31             sum2[i][j]=mp[i][j]+sum2[i-1][j]; //上到下累加
    32         }
    33     for(int i=1;i<=n;i++)
    34         for(int j=1;j<=m;j++)
    35         {
    36             if( mp[i][j] )  continue;
    37             if(sum1[i][j]>0)            cnt++; //左边有人
    38             if(sum1[i][j]<sum1[i][m])   cnt++; //右边有人
    39             if(sum2[i][j]>0)            cnt++; //上边有人
    40             if(sum2[i][j]<sum2[n][j])   cnt++; //下边有人
    41         }
    42 
    43     cout<<cnt<<endl;
    44 }
  • 相关阅读:
    【洛谷 P1896】[SCOI2005]互不侵犯(状压dp)
    【洛谷 P4289】[HAOI2008]移动玩具(搜索)
    【洛谷 SP283】NAPTIME
    【洛谷 P4342】[IOI1998]Polygon(DP)
    【洛谷 SP2878】Knights of the Round Table(双联通分量)
    【洛谷 P4168】[Violet]蒲公英(分块)
    【洛谷 P4180】【模板】严格次小生成树[BJWC2010](倍增)
    数学总结
    个人码风
    【洛谷 P3304】[SDOI2013]直径(树的直径)
  • 原文地址:https://www.cnblogs.com/thunder-110/p/9279493.html
Copyright © 2020-2023  润新知