题目链接:
https://vjudge.net/contest/208482#problem
题目大意:
给你一个N*M的空间,其中0表示没有人,1表示有人,对应一个好位子以及方向的定义为:
①首先这个位子不能有人。
②其次对应这个位子安排一个照明方向,这个方向上必须有人才行。
让你求一共有多少个这样满足的放置方案。
数据范围:
1 <= n, m <=1000 ;
输入输出格式:
Input
2 4 0 1 0 0 1 0 1 0
Output
9
Input
4 4 0 0 0 0 1 0 0 1 0 1 1 0 0 1 0 0
Output
20
解题思路:
此题暴力的话会在TLE在第七个样例上;因此要先做预处理,用两个数组sum1,sum2分别存放行的前缀和、列的前缀和。
然后用一层循环判断当a[i][j] == 0 时 :
<1> 判断sum1[i][j] >? 0, sum1[i][m] - sum1[i][j] > ? 0;
<2> 判断sum2[i][j] >? 0, sum2[i][n] - sum2[i][j] > ? 0;
若大于 0 ,则ans++;
这个题比较坑的一个地方是输入输出使用C++的输入输出流的话还是会TLE, 要换成 scanf()和printf()
因此当我们遇到TLE 时 ,不能忽略这个问题(尽量用scanf() 和 printf() : )
AC代码:
#include <bits/stdc++.h>
#define m(a,b) memset(a,b,sizeof(a))
typedef long long LL;
const int MAX = 1000;
using namespace std;
int tu[MAX+5][MAX+5],m,n;
int sum1[MAX+5][MAX+5],sum2[MAX+5][MAX+5];
int main(){
scanf("%d%d",&n,&m);
m(sum1,0),m(sum2,0);
for(int i=1; i<=n; ++i){
for(int j=1; j<=m; ++j){
scanf("%d",&tu[i][j]);
sum1[i][j]=sum1[i][j-1]+tu[i][j];
sum2[i][j]=sum2[i-1][j]+tu[i][j];
}
}
int ans = 0;
for(int i=1; i<=n; ++i){
for(int j=1; j<=m; ++j){
if(tu[i][j]==0){
if(sum2[n][j]-sum2[i][j]>0)ans++;
if(sum2[i][j]>0)ans++;
if(sum1[i][m]-sum1[i][j]>0)ans++;
if(sum1[i][j]>0)ans++;
}
}
}
printf("%d\n",ans);
return 0;
}