hdu 4517 小小明系列故事——游戏的烦恼(统计类题目)
Problem Description
小小明最近在玩一款游戏,它由n*m大小的矩阵构成,矩阵上会随机产生一些黑色的点,这些点它们可能会连在一起也可能会分开,这些点的个数没有限制,但是每个1*1方格中最多只可能有一个黑点产生。游戏要求玩家以最短的时间用x*y的小矩阵覆盖这个大矩阵,覆盖的要求有以下2点:
1. x*y大小的小矩阵内必须有x*y个黑点。
2. 多个小矩阵可以重叠,但是每个小矩阵放置的位置必须是独一无二的,即不同的小矩阵内的黑点不能完全相同。例如1*2的矩阵可以横着放,也可以竖着放,这两种方法是不同的,即使它们可能共用黑点。
小小明是个粗心的孩子,他尝试了很多遍都无法将所有的符合要求的小矩阵找到,聪明的你,能不能告诉烦恼中的小小明这个大矩阵里有多少个满足要求的小矩阵呢?
1. x*y大小的小矩阵内必须有x*y个黑点。
2. 多个小矩阵可以重叠,但是每个小矩阵放置的位置必须是独一无二的,即不同的小矩阵内的黑点不能完全相同。例如1*2的矩阵可以横着放,也可以竖着放,这两种方法是不同的,即使它们可能共用黑点。
小小明是个粗心的孩子,他尝试了很多遍都无法将所有的符合要求的小矩阵找到,聪明的你,能不能告诉烦恼中的小小明这个大矩阵里有多少个满足要求的小矩阵呢?
做法:关键是统计每个矩形的面积,刚开始用二维树状数组来统计超时了。其实用递推的方法可以很快的预处理求出矩形(1,1)~(i,j)的面积,接下来枚举每个符合条件的矩形,判断其面积是否等于x*y即可。
View Code
1 /* 2 *Author: Zhaofa Fang 3 *Created time: 2013-03-23-21.36 4 *Language: C++ 5 */ 6 #include <cstdio> 7 #include <cstdlib> 8 #include <sstream> 9 #include <iostream> 10 #include <cmath> 11 #include <cstring> 12 #include <algorithm> 13 #include <string> 14 #include <utility> 15 #include <vector> 16 #include <queue> 17 #include <stack> 18 #include <map> 19 #include <set> 20 using namespace std; 21 22 typedef long long ll; 23 #define DEBUG(x) cout<< #x << ':' << x << endl 24 #define REP(i,n) for(int i=0;i < (n);i++) 25 #define REPD(i,n) for(int i=(n-1);i >= 0;i--) 26 #define FOR(i,s,t) for(int i = (s);i <= (t);i++) 27 #define FORD(i,s,t) for(int i = (s);i >= (t);i--) 28 #define PII pair<int,int> 29 #define PB push_back 30 #define MP make_pair 31 #define ft first 32 #define sd second 33 #define lowbit(x) (x&(-x)) 34 #define INF (1<<30) 35 36 int n,m; 37 int C[2011][2011]; 38 char str[2011][2011]; 39 40 41 void fun(){ 42 C[0][0] = 0; 43 FOR(i,1,n){ 44 C[i][0] = 0; 45 FOR(j,1,m){ 46 C[i][j] = C[i][j-1]+(str[i][j]=='*'?1:0); 47 } 48 } 49 FOR(i,2,n){ 50 FOR(j,1,m){ 51 C[i][j] += C[i-1][j]; 52 } 53 } 54 } 55 int Area(int x1,int y1,int x2,int y2){ 56 if(x1>x2)swap(x1,x2); 57 if(y1>y2)swap(y1,y2); 58 return C[x2][y2]-C[x2][y1-1]-C[x1-1][y2]+C[x1-1][y1-1]; 59 } 60 61 int main() 62 { 63 //freopen("in","r",stdin); 64 //freopen("out","w",stdout); 65 while(~scanf("%d%d",&n,&m),n,m){ 66 int x,y; 67 scanf("%d%d",&x,&y); 68 FOR(i,1,n)scanf("%s",str[i]+1); 69 fun(); 70 int ans = 0; 71 FOR(i,1,n){ 72 FOR(j,1,m){ 73 if(str[i][j] != '*')continue; 74 int xx1 = i+x-1; 75 int yy1 = j+y-1; 76 if(!(xx1<1||yy1<1||xx1>n||yy1>m)){ 77 if(Area(i,j,xx1,yy1) == x*y)ans++; 78 79 } 80 81 int xx2 = i+y-1; 82 int yy2 = j+x-1; 83 if(xx2 == xx1 && yy2==yy1)continue; 84 if(xx2<1||yy2<1||xx2>n||yy2>m)continue; 85 if(Area(i,j,xx2,yy2) == x*y)ans++; 86 87 } 88 } 89 printf("%d\n",ans); 90 } 91 return 0; 92 }
by Farmer