社团游戏

链接: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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值