旋转坐标+前缀和(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; }