题目大意:
在一个平面内,一头奶牛只能吃距离它k步的地点上的草。请问这只奶牛最多能吃到多少草?
思路:
一开始看到这道题时一头雾水,以为要像懒惰的奶牛①一样,把平面转换成直线。但是想了一下,发现对于不确定的点f[i][j],我们无法确定每个点距离它多少米,枚举的话必然超时。
在草稿纸上画了几下之后,我发现了这道题的正解。
无n等于几还有k等于几,奶牛能吃到的草总是一个正方形!
那我们可以先求出f[i][j]的前缀和,计算一个正方形的时候,再利用前缀和求出第i行的能吃到的青草数。这样只要for循环2*k-1次,就可以求出一个点能吃到的青草数,就不会超时。
代码:
#include <cstdio>
#include <map>
using namespace std;
int f[402][402],n,m,sum,maxn,q,ok;
int main()
{
freopen("lazy_silver.in","r",stdin);
freopen("lazy_silver.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
scanf("%d",&f[i][j]);
f[i][j]+=f[i][j-1]; //计算f[i][j]的前缀和
}
}
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++) //枚举每一个点
{
sum=0;
for (int k=i-m;k<=i+m;k++) //求一个点能吃到的青草数
{
if(k<1) k=1;
if(k>n) break; //防止数组越界
int t=i-k>0?i-k:k-i;
int u=j+m-t>n?n:j+m-t;
int v=j-m+t<1?1:j-m+t; //计算第i行能吃到的青草数
sum+=f[k][u]-f[k][v-1]; //计算在第i行j列能吃到的青草数
}
if (sum>maxn) maxn=sum; //求最大值
}
}
printf("%d",maxn);
return 0;
}