codeforces 677E

题意:给出一个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
 */




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值