1. 程式人生 > >Spotlights【思維+前綴和優化】

Spotlights【思維+前綴和優化】

設定 tac 時間復雜度 vector for 人的 names net stream

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 }

Spotlights【思維+前綴和優化】