赞
踩
小美的字符串变换(卡码网周赛第二十一期(23年美团笔试真题))
小美拿到了一个长度为 n 的字符串,她希望将字符串从左到右平铺成一个矩阵(先平铺第一行,然后是第二行,以此类推,矩阵有 x 行 y 列,必须保证 x * y=n,即每 y 个字符换行,共 x 行)。
该矩阵的权值定义为这个矩阵的连通块数量。小美希望最终矩阵的权值尽可能小,你能帮小美求出这个最小权值吗?
注:我们定义,上下左右四个方向相邻的相同字符是连通的。
第一行输入一个正整数 n(1 <= n <= 10^4),代表字符串的长度。
第二行输入一个长度为 n 的、仅由小写字母组成的字符串。
输出一个整数表示最小权值。
9
aababbabb
2
平铺为 3 * 3 的矩阵:
aab
abb
abb
共有 2 个连通块,4 个 a 和 5 个 b。
#include<bits/stdc++.h> using namespace std; const int N = 1e4 + 10; const int dx[] = {0, 1, -1, 0}; const int dy[] = {1, 0, 0, -1}; char s[N]; int n, Width, Lenth; bool vis[N]; struct node{ int x, y; }now; bool check(int x, int y){ if(x <= 0 || x > Lenth || y <= 0 || y > Width || (x - 1)*Width + y <= 0 || (x - 1)*Width + y > n || vis[(x - 1)*Width + y]) return false; return true; } void bfs(int x, int y){ queue<node> q; vis[(x - 1)*Width + y] = 1; q.push({x, y}); while(!q.empty()){ now = q.front(); q.pop(); char c = s[(now.x - 1)*Width + now.y]; for(int i = 0; i < 4; i++){ int tx = now.x + dx[i]; int ty = now.y + dy[i]; if(!check(tx, ty) || s[(tx - 1)*Width + ty] != c) continue; vis[(tx - 1)*Width + ty] = 1; q.push({tx, ty}); } } } /* 8 aabaabab 针对 2 * 4 与 4 * 2 这两种情况来讲,长宽分别是2,4,但连通块数量却不同 1、 aaba 有6个连通块 abab 2、 aa 有4个连通块 ba ab ab */ int main(){ scanf("%d%s", &n, s + 1); int ans = n; for(int i = 1; i <= n; i++){ int sum = 0; if(i*(n/i)==n){ // 长与宽可以构成一个长方形 memset(vis, 0, sizeof vis); Lenth = i; Width = n/i; for(int lenth = 1; lenth <= Lenth; lenth++){ for(int width = 1; width <= Width; width++){ if(!vis[(lenth - 1)*Width + width]){ bfs(lenth, width); sum++; } } } ans = min(ans, sum); } } printf("%d\n", ans); return 0; }
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。