这题最大的收获,不是对于dp的思考,而是以非循环量代替循环量来简化问题的思想。
这题是maximum sum的升级版,不同之处在于数组可以循环,解决办法就是再在三个方向上复制原数组,不过需要注意控制子矩形的尺寸不能超过n*n。
开始用类似上题的办法dp,超时,后来用了暴力加上一些性质才ac.
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAX 80
using namespace std;
int s[MAX*2-1][MAX*2-1],sum[MAX*2-1][MAX*2-1];
int main()
{
int t,n,i,j,p,q,maxx,temp;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&s[i][j]);
for(i=n;i<n*2-1;i++)
for(j=0;j<n;j++)
s[i][j]=s[i-n][j];
for(i=0;i<n;i++)
for(j=n;j<2*n-1;j++)
s[i][j]=s[i][j-n];
for(i=n;i<n*2-1;i++)
for(j=n;j<n*2-1;j++)
s[i][j]=s[i-n][j-n];
maxx=-100000000;
//sum[0][0]=s[0][0];
for(i=0;i<n*2-1;i++)
{
for(j=0;j<n*2-1;j++)
{
sum[i][j]=s[i][j];
if(j-1>=0)
sum[i][j]+=sum[i][j-1];
if(i-1>=0)
sum[i][j]+=sum[i-1][j];
if(j-1>=0&&i-1>=0)
sum[i][j]-=sum[i-1][j-1];
}
}
for(i=0;i<n*2-1;i++)
{
for(j=0;j<n*2-1;j++)
{
for(p=i;p<i+n&&p<n*2-1;p++)
{
for(q=j;q<j+n&&q<n*2-1;q++)
{
temp=sum[p][q];
if(j-1>=0)
temp-=sum[p][j-1];
if(i-1>=0)
temp-=sum[i-1][q];
if(j-1>=0&&i-1>=0)
temp+=sum[i-1][j-1];
if(temp>maxx)
maxx=temp;
}
}
}
}
printf("%d\n",maxx);
}
return 0;
}