旋转坐标+前缀和(zqu 25001)

本题题意:在一个矩阵中,去随机一点,设定一个步数K,求出从这个点可以走到的范围的和,求最大值

思路:这个范围的和是一个菱形,我们把他旋转45°,然后成为一个正放的矩阵,求出二维前缀和

然后用前缀和的性质枚举每一块矩阵的大小,更新答案

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=405;
int a[maxn][maxn];
int b[maxn*2][maxn*2];
int main()
{
    int n,m,k,x,y,xl,yl,xr,yr;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&a[i][j]);
    m=n*2-1;//新矩阵的大小
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            b[i+j-1][n-i+j]=a[i][j];//把矩阵旋转过来
//    for(int i=1;i<=m;i++){
//        for(int j=1;j<=m;j++){
//            printf("%d ",b[i][j]);
//        }
//        printf("\n");
//    }
    for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++)
            b[i][j]+=b[i][j-1];//前缀和
    for(int j=1;j<=m;j++)
        for(int i=1;i<=m;i++)
            b[j][i]+=b[j-1][i];//前缀和
    int ans=0;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++){
        x=i+j-1,y=n-i+j;//求旋转后的坐标
        xl=x-k,yl=y-k,xr=x+k,yr=y+k;//求左上角、右下角的坐标
        if(xl<1) xl=1;
        if(yl<1) yl=1;
        if(xr>m) xr=m;
        if(yr>m) yr=m;//超出矩阵外的部分要去掉
        ans=max(ans,b[xr][yr]-b[xr][yl-1]-b[xl-1][yr]+b[xl-1][yl-1]);//更新答案
    }
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2019-09-20 17:04  古比  阅读(191)  评论(0编辑  收藏  举报