https://codeforces.com/problemset/problem/1453/C
아이디어 :
한쪽 모서리가 평행한지 확인한 다음이 모서리를 열거합니다.
시작 아이디어는 열거 형 O (10 * 2000 * 2000)에 의해 도달 한 포인트를 k로 열거 한 다음 오른쪽 행, 왼쪽 행, 맨 위 열, 열을 사전 처리하는 것입니다. k의 위치, 그리고 답을 꺼내면 실제로 할 수 있습니다. 그러나 코드의 양은 약간 번거롭고 생각이 간결하지 않습니다.
마지막으로 욕심 많은 구성 방법으로 변경된 점을 처리하고, 먼저 숫자 k의 맨 위 행 위치, 맨 아래 행 위치, 맨 왼쪽 행 위치, 맨 오른쪽 행 위치를 먼저 처리 한 다음 O (2000 * 2000) 열거, For 열거 된 k, 우리는 그가 네 방향 각각에 대해 최대 값을 취하도록했습니다. 여기에 예가 있습니다.
세 번째 행에 2가 있습니다. 가장 큰 값은 아래에서 가장 먼 두 행과 세 번째 행의 차이에서 파생됩니다. 그러면 질문은 병렬 처리가 필요합니다. 다음이 병렬인지 여부에 관계없이 수정 된 점을 던집니다. 여기에서 가장 왼쪽 또는 가장 오른쪽 행이 최상이고 조건을 충족해야하며 O (2000 * 2000)이 스캔됩니다. (정수 10 개도 누락 됨)
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e3+100;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL maxx[maxn],minx[maxn],maxy[maxn],miny[maxn];
LL a[maxn][maxn];
char s[maxn][maxn];
LL ans[20];
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL T;cin>>T;
while(T--){
LL n;cin>>n;
for(LL i=0;i<n+10;i++) maxx[i]=0,minx[i]=n,maxy[i]=0,miny[i]=n;
for(LL i=0;i<20;i++) ans[i]=0;
for(LL i=1;i<=n;i++){
for(LL j=1;j<=n;j++) cin>>s[i][j];
}
for(LL i=1;i<=n;i++){
for(LL j=1;j<=n;j++) a[i][j]=(s[i][j]-'0');
}
for(LL i=1;i<=n;i++){
for(LL j=1;j<=n;j++){
LL t=a[i][j];
maxx[t]=max(maxx[t],i);
minx[t]=min(minx[t],i);
maxy[t]=max(maxy[t],j);
miny[t]=min(miny[t],j);
}
}
for(LL i=1;i<=n;i++){
for(LL j=1;j<=n;j++){
LL t=a[i][j];
ans[t]=max(ans[t],abs(maxx[t]-i)*max(n-j,j-1) );
ans[t]=max(ans[t],abs(i-minx[t])*max(n-j,j-1) );
ans[t]=max(ans[t],abs(maxy[t]-j)*max(n-i,i-1) );
ans[t]=max(ans[t],abs(miny[t]-j)*max(n-i,i-1) );
}
}
for(LL i=0;i<10;i++){
cout<<ans[i]<<" ";
}
cout<<"\n";
}
return 0;
}