题意:给出一个1000*1000的方阵,问你任意“十字乘积”的最大值。十字可以是对角线的,四边长度要相等。
题解:用8个数组维护8个方向的乘积,枚举任意一个点。(乘积最大相应的取对数也是最大的,将n项乘积转换成前n项和)。
#include<bits/stdc++.h>
using namespace std;
#define N 2010
int d[N][N];
double s[8][N][N];
int p[8][N][N];
typedef long long LL;
#define MOD 1000000007
//0,1 ,1,1, 1,0, 1,-1, 0,-1, -1,-1, -1,0, -1,1
int dre[]={0,1 ,1,1, 1,0, 1,-1, 0,-1, -1,-1, -1,0, -1,1};
double lg[4];
inline bool check(int x,int y,int n,int m){
return x>=1&&x<=n&&y<=m&&y>=1;
}
void dfs(int x,int y,int k,int n,int m){
int pr = dre[k*2],pc = dre[k*2+1];
int tx = x+pr,ty=y+pc;
if(check(tx,ty,n,m)){
if(d[tx][ty]==0){
s[k][tx][ty]=0;
p[k][tx][ty]=0;
}else{
s[k][tx][ty]=s[k][x][y]+lg[d[tx][ty]];
// if(k==3){
// printf("%d,%d(%.2lf)--->%d,%d(%.2lf,%d,%.2lf)\n",x,y,s[k][x][y],tx,ty,s[k][tx][ty],d[tx][ty],lg[d[tx][ty]]);
// }
p[k][tx][ty]=p[k][x][y]+1;
}
dfs(tx,ty,k,n,m);
}
}
int main(){
int n;
lg[1]=0,lg[2]=log(2.),lg[3]=log(3.);
//lg[1]=1,lg[2]=2,lg[3]=3;
while(scanf(" %d",&n)==1){
//vector<vector<int> > d(n+2,vector<int>(n+2,0));
for(int i=0;i<=n+1;i++){
for(int j=0;j<=n+1;j++){
d[i][j]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf(" %1d",&d[i][j]);
}
}
// for(int i=1;i<=n;i++){
// for(int j=1;j<=n;j++){
// printf("%d ",d[i][j]);
// }
// puts("");fflush(stdout);
// }
for(int k=0;k<8;k++){
for(int i=0;i<=n+1;i++){
p[k][i][0]=0;
s[k][i][0]=0;
dfs(i,0,k,n,n);
p[k][i][n+1]=0;
s[k][i][n+1]=0;
dfs(i,n+1,k,n,n);
}
for(int j=0;j<=n+1;j++){
p[k][0][j]=0;
s[k][0][j]=0;
dfs(0,j,k,n,n);
p[k][n+1][j]=0;
s[k][n+1][j]=0;
dfs(n+1,j,k,n,n);
}
}
// for(int k=0;k<8;k++){
// printf("K:%d\n",k);
// for(int i=1;i<=n;i++){
// for(int j=1;j<=n;j++){
// printf("%.2lf(%d) ",s[k][i][j],p[k][i][j]);
// }
// puts("");fflush(stdout);
// }
// }
double ms = -1;
int rx,ry,t=-1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(d[i][j]==0) continue;
int dm = p[0][i][j];
for(int k=0;k<=6;k+=2){
dm = min(dm,p[k][i][j]);
}
//printf("%d %d(t1)(%d)\n",i,j,dm);
double ts = 0;
for(int k=0;k<=6;k+=2){
ts += s[k][i][j]-s[k][i-(dre[k*2]*dm)][j-dre[2*k+1]*dm];
}
ts -= lg[d[i][j]] * 3;
if(ts>ms){
ms = ts;
t = 1;
rx = i;
ry = j;
}
dm = p[1][i][j];
for(int k=3;k<=7;k+=2){
dm = min(dm,p[k][i][j]);
}
//printf("%d %d(t2)(%d)\n",i,j,dm);
ts = 0;
for(int k=1;k<=7;k+=2){
ts += s[k][i][j] - s[k][i-(dre[k*2]*dm)][j-dre[2*k+1]*dm];
}
ts -= lg[d[i][j]] * 3;
if(ts>ms){
ms = ts;
t = 2;
rx = i;
ry = j;
}
}
}
//printf("%d %d %d\n",rx,ry,t);
if(t==-1){
printf("0\n");
continue;
}
LL ret = 1;
if(t==1){
int dm = p[0][rx][ry];
for(int k=0;k<=6;k+=2){
dm = min(dm,p[k][rx][ry]);
}
ret = d[rx][ry];
for(int k=0;k<=6;k+=2){
for(int j = 1;j<dm;j++){
ret = ret*d[rx-dre[k*2]*j][ry-dre[2*k+1]*j]%MOD;
}
}
}else{
int dm = p[1][rx][ry];
for(int k=1;k<=7;k+=2){
dm = min(dm,p[k][rx][ry]);
}
//printf("%d %d %d\n",rx,ry,dm);
ret = d[rx][ry];
for(int k=1;k<=7;k+=2){
for(int j = 1;j<dm;j++){
ret = ret*d[rx-dre[k*2]*j][ry-dre[2*k+1]*j]%MOD;
}
}
}
printf("%I64d\n",ret);
//fflush(stdout);
}
return 0;
}
/*
4
1233
0213
2020
0303
*/