链接:https://ac.nowcoder.com/acm/contest/11319/H
来源:牛客网
题目描述
在民风淳朴的雏见泽,号称能“完美犯罪”的天才牛牛,又开始和社团的萌妹子牛妹玩起了游戏。
在今天的游戏中,牛牛将会得到一个n\times mn×m且全为小写字母的矩阵,他可以从矩阵中任选一块正方形,但必须保证该正方形中任意一类小写字母个数之和不能超过kk,换而言之,在该正方形中,‘a’字符个数不能超过kk,‘b’字符个数不能超过kk,…,‘z’字符个数不能超过kk。
现在牛牛想知道,以(i,j)(i,j)为左上角且符合以上要求的正方形中,边长最大的是多少?
输入描述:
第一行三个正整数nn,mm,kk,其中:n\leq500n≤500,m\leq500m≤500,k\leq10^{9}k≤10
9
。
接下来nn行,每行mm个小写字母。
输出描述:
输出nn行,每行mm个数字。其中第ii行第jj个数字表示,以(i,j)(i,j)为左上角且符合题目要求的正方形的最大边长。
示例1
输入
复制
3 3 2
aaa
bcd
efg
输出
复制
2 2 1
2 2 1
1 1 1
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 510;
char s[N][N];
int f[N][N][30];
int main(){
int n, m, w;
scanf("%d%d%d", &n, &m, &w);
for (int i = 1; i <= n; i ++) scanf("%s", s[i] + 1);
for (int i = 1; i <= n; i ++){
for (int j = 1; j <= m; j ++){
int x = (s[i][j] - 'a' + 1);
for (int k = 1; k <= 26; k ++){
if (x == k){
f[i][j][k] = f[i][j - 1][k] + f[i - 1][j][k] - f[i - 1][j - 1][k] + 1;
}
else {
f[i][j][k] = f[i][j - 1][k] + f[i - 1][j][k] - f[i - 1][j - 1][k];
}
}
}
}
for (int i = 1; i <= n; i ++){
for (int j = 1; j <= m; j ++){
int r1 = (m - j + 1);
int down1 = (n - i + 1);
int len = min(r1, down1);
int l = 1, r = len;
while(l < r){
int mid = (l + r + 1) >> 1;
int r2 = j + mid - 1;
int down2 = i + mid - 1;
bool flag = false;
for (int k = 1; k <= 26; k ++){
if (f[down2][r2][k] + f[i - 1][j - 1][k] - f[i - 1][r2][k] -f[down2][j - 1][k] > w) flag = true;
}
if (!flag) l = mid;
else r = mid - 1;
}
cout << l << " ";
}
cout << endl;
}
return 0;
}