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);
}
}