SSLZYC 懒惰的奶牛②

题目大意:
在一个平面内,一头奶牛只能吃距离它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; 
}
原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313122.html