#include<bits/stdc++.h>#define int long longusingnamespacestd;constintMAXN=2000+5;inta[MAXN][MAXN];intdp1[MAXN][MAXN],dp2[MAXN][MAXN],dp3[MAXN][MAXN],dp4[MAXN][MAXN];signedmain(){intn,m;cin>>n>>m;for(inti=1;i<=n;i++){strings;cin>>s;for(intj=1;j<=m;j++){a[i][j]=s[j-1]-'a'+1;}}for(inti=1;i<=n;i++){for(intj=1;j<=m;j++){if(a[i][j]==a[i-1][j]&&a[i][j]==a[i][j-1]){dp1[i][j]=min(dp1[i-1][j],dp1[i][j-1])+1;}else{dp1[i][j]=1;}}}for(inti=1;i<=n;i++){for(intj=m;j>=1;j--){if(a[i][j]==a[i-1][j]&&a[i][j]==a[i][j+1]){dp2[i][j]=min(dp2[i-1][j],dp2[i][j+1])+1;}else{dp2[i][j]=1;}}}for(inti=n;i>=1;i--){for(intj=1;j<=m;j++){if(a[i][j]==a[i+1][j]&&a[i][j]==a[i][j-1]){dp3[i][j]=min(dp3[i+1][j],dp3[i][j-1])+1;}else{dp3[i][j]=1;}}}for(inti=n;i>=1;i--){for(intj=m;j>=1;j--){if(a[i][j]==a[i+1][j]&&a[i][j]==a[i][j+1]){dp4[i][j]=min(dp4[i+1][j],dp4[i][j+1])+1;}else{dp4[i][j]=1;}}}intans=0;for(inti=1;i<=n;i++){for(intj=1;j<=m;j++){ans+=min({dp1[i][j],dp2[i][j],dp3[i][j],dp4[i][j]});}}cout<<ans<<'\n';}
最大子正方形 變化 1
給一個 n x m 的 01 方格圖,可以將 row 兩兩 swap,可以做任意次,找出面積最大的正方形只包含 1
hint
Hint: 對於每一個直行 (column),若有超過 k 個以該 column 為結尾且長度超過 k 的橫列 (row),則找到一個 k * k 的正方形
思路
二分搜 k,對於每一個 column,檢查是否有超過 k 個以該 column 為結尾且長度超過 k 的橫列 row,複雜度 O(nm log n)
最大子正方形 變化 2
給一個 n x m 的 01 方格圖,可以將 row 兩兩 swap,也可以將 column 兩兩 swap,都可以做任意次,找出面積最大的正方形只包含 1
思路
原題可轉為挑一些 row 子集和一些 col 子集,row 和 col 挑的數量相同,且這些 row col 交集處為全 1
for(inti=0;i<m;i++)dp[i][0]=1;intmx=0;for(intmask=1;mask<(1<<n);mask++){intcnt=0;intcur=__builtin_ctz(mask);intsz=__builtin_popcountll(mask);for(inti=0;i<m;i++){if(a[cur][i]==1&&dp[i][mask^(1<<cur)]){dp[i][mask]=1;cnt++;}}if(cnt>=sz){mx=max(mx,sz*sz);}}// mx is the final ans