目录
[Q1. 检查平衡字符串](#Q1. 检查平衡字符串)
[Q2. 到达最后一个房间的最少时间 I](#Q2. 到达最后一个房间的最少时间 I)
[Q3. 到达最后一个房间的最少时间 II](#Q3. 到达最后一个房间的最少时间 II)
[Q4. 统计平衡排列的数目](#Q4. 统计平衡排列的数目)
Q1. 检查平衡字符串
原题链接
思路分析
签到题,不说了
时间复杂度:O(N)
AC代码
python
class Solution:
def isBalanced(self, num: str) -> bool:
num = list(map(ord, num))
for i in range(len(num)):
num[i] -= ord('0')
return sum(num[0::2]) == sum(num[1::2])
Q2. 到达最后一个房间的最少时间 I
原题链接
思路分析
无脑 dij 即可
时间复杂度:O(NM log NM)
AC代码
cpp
using i64 = long long;
constexpr i64 inf64 = 1E18 + 7;
int dir[] = {-1, 0, 1, 0, -1};
class Solution {
public:
int minTimeToReach(vector<vector<int>>& moveTime) {
int n = moveTime.size(), m = moveTime[0].size();
std::priority_queue<std::tuple<i64, int, int, int>, std::vector<std::tuple<i64, int, int, int>>, std::greater<std::tuple<i64, int, int, int>>> pq;
std::vector<std::vector<i64>> dis(n, std::vector<i64>(m, inf64));
pq.emplace(0, 0, 0, 1);
dis[0][0] = 0;
while (pq.size()) {
auto [d, i, j, w] = pq.top();
pq.pop();
if (d > dis[i][j]) {
continue;
}
for (int k = 0; k < 4; ++ k) {
auto [ni, nj] = std::pair(i + dir[k], j + dir[k + 1]);
if (ni < 0 || ni >= n || nj < 0 || nj >= m) {
continue;
}
i64 nd = std::max<i64>(d, moveTime[ni][nj]) + w;
i64 nw = 1;
if (dis[ni][nj] > nd) {
dis[ni][nj] = nd;
pq.emplace(nd, ni, nj, nw);
}
}
}
return dis[n - 1][m - 1];
}
};
Q3. 到达最后一个房间的最少时间 II
原题链接
思路分析
无脑dij即可
时间复杂度:O(NM log NM)
AC代码
cpp
using i64 = long long;
constexpr i64 inf64 = 1E18 + 7;
int dir[] = {-1, 0, 1, 0, -1};
class Solution {
public:
int minTimeToReach(vector<vector<int>>& moveTime) {
int n = moveTime.size(), m = moveTime[0].size();
std::priority_queue<std::tuple<i64, int, int, int>, std::vector<std::tuple<i64, int, int, int>>, std::greater<std::tuple<i64, int, int, int>>> pq;
std::vector<std::vector<i64>> dis(n, std::vector<i64>(m, inf64));
pq.emplace(0, 0, 0, 1);
dis[0][0] = 0;
while (pq.size()) {
auto [d, i, j, w] = pq.top();
pq.pop();
if (d > dis[i][j]) {
continue;
}
for (int k = 0; k < 4; ++ k) {
auto [ni, nj] = std::pair(i + dir[k], j + dir[k + 1]);
if (ni < 0 || ni >= n || nj < 0 || nj >= m) {
continue;
}
i64 nd = std::max<i64>(d, moveTime[ni][nj]) + w;
i64 nw = (w + 1) % 3;
if (nw == 0) {
nw = 1;
}
if (dis[ni][nj] > nd) {
dis[ni][nj] = nd;
pq.emplace(nd, ni, nj, nw);
}
}
}
return dis[n - 1][m - 1];
}
};
Q4. 统计平衡排列的数目
原题链接
思路分析
记忆化搜索 + 组合数学
考虑 dfs(i, j, k) 为 奇位置的 序列,考虑到填 数字 i,和为 j,长度为 k时的 方案数
如果我们填了 c 个 i,那么 有 cnt[i] - c 个 i 填到 偶数位置
由于要求排列数,而奇偶位置的排列显然都是多重集排列
多重集排列数 = n! / p1! p2!...pk!
由于本题是取模,所以分母可以在递归的时候乘其逆元
即 dfs(i, j, k) = Σ dfs(i + 1, j + c * i, k + c) * inv(fac(c)) * inv(fac(cnt[i] - c))
时间复杂度:O(U^2 N^3),U = 10
AC代码
python
P = 1_000_000_007
N = 80
fac = [1] * (N + 1)
inv = [1] * (N + 1)
for i in range(2, N + 1):
fac[i] = fac[i - 1] * i % P
inv[N] = pow(fac[N], P - 2, P)
for i in range(N - 1, 1, -1):
inv[i] = (i + 1) * inv[i + 1]
class Solution:
def countBalancedPermutations(self, num: str) -> int:
num = list(map(ord, num))
s = 0
for i in range(len(num)):
num[i] -= ord('0')
s += num[i]
cnt = Counter(num)
if s & 1: return 0
@cache
def dfs(i: int, j: int, k: int) -> int:
if j * 2 > s: return 0
if i == 10:
return fac[len(num) // 2] * fac[(len(num) + 1) // 2] % P if j * 2 == s and k == len(num) // 2 else 0
res = 0
for c in range(cnt[i] + 1):
res += dfs(i + 1, j + c * i, k + c) * inv[c] * inv[cnt[i] - c] % P
res %= P
return res
dfs.cache_clear()
return dfs(0, 0, 0)