题解
为了计算面积,需将三角形中与网格平行的边作为三角形的底。显然底越长面积越大,因此对于点\(A\),可以将满足\(AB\)与网格平行且距离最长的\(B\)的数值改为与\(A\)一样。而另一个顶点为满足高最长,一定是\(d\)数值可以到达的最上、最下、最左或最右的格点,预处理即可。
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N=2010;
char mp[N][N];
int d[N][N],pos[20][10],ans[20];
//pos[i][j]:数值为i的格点最上(0)下(1)左(2)右(3)的行/列号
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
memset(pos,-1,sizeof(pos));
memset(ans,0,sizeof(ans));
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) d[i][j]=mp[i][j]-'0';
//预处理pos数组
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int tmp=d[i][j];
if(pos[tmp][0]>i || pos[tmp][0]==-1) pos[tmp][0]=i;
if(pos[tmp][1]<i) pos[tmp][1]=i;
if(pos[tmp][2]>j || pos[tmp][2]==-1) pos[tmp][2]=j;
if(pos[tmp][3]<j) pos[tmp][3]=j;
}
}
//枚举前文中的点A,统计答案
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int tmp=d[i][j];
ans[tmp]=max(ans[tmp],max(n-i,i-1)*(pos[tmp][3]-j));
ans[tmp]=max(ans[tmp],max(n-i,i-1)*(j-pos[tmp][2]));
ans[tmp]=max(ans[tmp],max(n-j,j-1)*(pos[tmp][1]-i));
ans[tmp]=max(ans[tmp],max(n-j,j-1)*(i-pos[tmp][0]));
}
}
for(int i=0;i<10;i++) printf("%d ",ans[i]);
printf("\n");
}
return 0;
}