最开始想到的枚举:
其实最开始想错了一些地方,或者说一些地方没有想清楚。
现在说一下改完之后的:
按行和列枚举点
第三层循环有两个 分别是鱼的对角线是从左上到右下 和 从左下到右上
枚举的点分别是正方形的左上角点和右上角点
分开来循环只有一个目的:方便剪枝
举个栗子:
4 6
0 1 0 1 0 0 我们现在枚举到(1, 2) 这个点
0 0 1 0 1 0 鱼在左上到右下的对角线的情况
1 1 0 0 0 1 枚举到正方形边长到3的时候就发现不行了
0 1 1 0 1 0 这时直接break 因为边长为4的情况肯定不行了要注意很多细节啊 调了挺久的
枚举 View Code1 #include<iostream> 2 #include<cstdio> 3 #define go(i,a,b) for(register int i=a;i<=b;i++) 4 #define M 2510 5 using namespace std; 6 int read() 7 { 8 int x=0,y=1;char c=getchar(); 9 while(c<'0'||c>'9') {if(c=='-') y=-1;c=getchar();} 10 while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();} 11 return x*y; 12 } 13 int n,m,ans=1; 14 bool mp[M][M],f1=0; 15 bool ck1(int x,int y,int k) 16 { 17 go(i,x,x+k) go(j,y,y+k) 18 { 19 if(i-x==j-y && !mp[i][j]) return 0; 20 if(i-x!=j-y && mp[i][j]) return 0; 21 } 22 return 1; 23 } 24 bool ck2(int x,int y,int k) 25 { 26 int z=x+y; 27 go(i,x,x+k) go(j,y-k,y) 28 { 29 if(i+j==z && !mp[i][j]) return 0; 30 if(i+j!=z && mp[i][j]) return 0; 31 } 32 return 1; 33 } 34 int main() 35 { 36 n=read();m=read(); 37 go(i,1,n) go(j,1,m) {mp[i][j]=read();if(mp[i][j]) f1=1;} 38 if(!f1) {puts("0");return 0;} 39 go(i,1,n) go(j,1,m) 40 { 41 int maxn=min(n-i+1,m-j+1); 42 go(k,ans+1,maxn) 43 { 44 if(ck1(i,j,k-1)) ans=k; 45 else break ; 46 } 47 maxn=min(n-i+1,j); 48 go(k,ans+1,maxn) 49 { 50 if(ck2(i,j,k-1)) ans=k; 51 else break ; 52 } 53 } 54 printf("%d",ans); 55 return 0; 56 }
本来以为会TLE几个点 结果 猝不及防地AC了??
不过挺慢的 2024ms 开O2 964ms
小结: 在打代码之前再理一理思路 从头到尾想一遍(毕竟我总是没想清楚而错)
然后又去想 DP:
然而我并不会
DP 题解View Code1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<string> 6 #include<map> 7 typedef long long ll; 8 using namespace std; 9 int n,m,ans; 10 int a[2509][2509],f[2509][2509],s1[2509][2509],s2[2509][2509];//s1为横向,s2为纵向 11 int main() 12 { 13 cin>>n>>m; 14 //第一遍左上——右下 15 for(int i=1;i<=n;i++) 16 for(int j=1;j<=m;j++) 17 { 18 scanf("%d",&a[i][j]); 19 if(!a[i][j]) 20 { 21 s1[i][j]=s1[i][j-1]+1; 22 s2[i][j]=s2[i-1][j]+1; 23 } 24 if(a[i][j]) 25 f[i][j]=min(f[i-1][j-1],min(s1[i][j-1],s2[i-1][j]))+1; 26 ans=max(ans,f[i][j]); 27 } 28 //第二遍右上——左下 29 memset(f,0,sizeof(f)); 30 memset(s1,0,sizeof(s1));//数组置0 31 memset(s2,0,sizeof(s2)); 32 for(int i=1;i<=n;i++) 33 for(int j=m;j>=1;j--) 34 { 35 if(!a[i][j]) 36 { 37 s1[i][j]=s1[i][j+1]+1; 38 s2[i][j]=s2[i-1][j]+1; 39 } 40 if(a[i][j]) 41 f[i][j]=min(f[i-1][j+1],min(s1[i][j+1],s2[i-1][j]))+1; 42 ans=max(ans,f[i][j]); 43 } 44 cout<<ans<<endl; 45 return 0; 46 }