POJ 2029 Get Many PersimmonTrees(二维树状数组or递推)
分析:这道题看起来能用很多方法做:递推,二维树状数组。
解法一:二维树状数组
先用二维树状数组来做:即一颗一颗的把树插入到树状数组中,然后遍历所有可行的格子(x,y)求出由(x-S+1,y-T+1)为左上角,(x,y)为右下角构成的矩形内有多少个树即可,该值为:
Sum(x,y)+sum(x-S,y-T)-sum(x,y-T)-sum(x-S,y)。
AC代码:16ms
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN=105; int c[MAXN][MAXN]; int W,H; int S,T; int lowbit(int x) { return x&(-x); } int sum(int i,int j) { int res=0; for(int x=i; x>0; x-=lowbit(x)) for(int y=j; y>0; y-=lowbit(y)) res +=c[x][y]; return res; } void add(int i,int j)//д╛хо╪с1 { for(int x=i; x<=W; x+=lowbit(x)) for(int y=j; y<=H; y+=lowbit(y)) c[x][y] +=1; } int main() { int N; while(scanf("%d",&N)==1&&N) { memset(c,0,sizeof(c)); scanf("%d%d",&W,&H); while(N--) { int x,y; scanf("%d%d",&x,&y); add(x,y); } scanf("%d%d",&S,&T); int max_num=0; for(int x=1; x+S-1<=W; x++) for(int y=1; y+T-1<=H; y++) { int temp = sum(x+S-1,y+T-1)+sum(x-1,y-1)-sum(x-1,y+T-1)-sum(x+S-1,y-1); max_num=max(max_num,temp); } printf("%d\n",max_num); } return 0; }
解法二:递推
要递推计算就要先计算所有的二维前缀和。令S[x][y]为以格子(1,1)为左上角,(x,y)为右下角的矩形中包含的树总数。
S[x][y] = S[x-1][y]+ S[x][y-1]- S[x-1][y-1]+A[x][y];其中A[x][y]=1表示(x,y)是树,否则不是树。
然后以(x,y)为左上角且以(x+W-1,y+H-1)为右下角的矩形中含有的树总数为:S[x+W-1][y+H-1]+S[x-1][y-1]-S[x-1][y+H-1]-S[x+W-1][y-1].
AC代码:0ms,递推更快点
//递推解法 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN=105; int a[MAXN][MAXN]; int s[MAXN][MAXN]; int W,H,S,T; int N; int main() { while(scanf("%d",&N)==1&&N) { memset(a,0,sizeof(a)); memset(s,0,sizeof(s)); scanf("%d%d",&W,&H); while(N--) { int x,y; scanf("%d%d",&x,&y); a[x][y]=1; } scanf("%d%d",&S,&T); for(int x=1;x<=W;x++) for(int y=1;y<=H;y++) { s[x][y]=s[x-1][y]+ s[x][y-1]- s[x-1][y-1]+a[x][y]; } int max_num=0; for(int x=1;x+S-1<=W;x++) for(int y=1;y+T-1<=H;y++) { int temp = s[x+S-1][y+T-1]+s[x-1][y-1]-s[x-1][y+T-1]-s[x+S-1][y-1]; max_num=max(max_num,temp); } printf("%d\n",max_num); } }