dijk|tire+floyd+dp %

算法 数学归纳+反证的角度 推理总结的思路

lc2575

% 步步取模 实现整数拆分

class Solution {

public:

vector<int> divisibilityArray(string word, int m) {

vector<int> ans(word.length());

long long x = 0;

for (int i = 0; i < word.length(); i++) {

++x = (x * 10 + (word[i] - '0')) % m;++

ans[i] = x == 0;

}

return ans;

}

};

lc2577

dijk 单源最短路 一开始只有一个起点 不可有负数

pq贪心更新 一步一步的取出 确定 选择

class Solution {

static constexpr int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

public:

int minimumTime(vector<vector<int>> &grid) {

int m = grid.size(), n = grid[0].size();

if (grid[0][1] > 1 && grid[1][0] > 1) // 无法「等待」

return -1;

int dis[m][n];

memset(dis, 0x3f, sizeof(dis));

dis[0][0] = 0;

priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<>> pq;

pq.emplace(0, 0, 0);

for (;;) { // 可以等待,就一定可以到达终点

auto[d, i, j] = pq.top();

pq.pop();

if (d > dis[i][j]) continue;

if (i == m - 1 && j == n - 1)

// 找到终点,此时 d 一定是最短路

return d;

for (auto &q : dirs) {

// 枚举周围四个格子

int x = i + q[0], y = j + q[1];

if (0 <= x && x < m && 0 <= y && y < n) {

int nd = max(d + 1, grid[x][y]);

nd += (nd - x - y) % 2;

// nd 必须和 x+y 同奇偶

++if (nd < dis[x][y]) {
dis[x][y] = nd;
++ // 更新最短路

pq.emplace(nd, x, y);

}

}

}

}

}

};

floyd 多源最短路

一种 选/不选 的dp思想

class Solution {

public:

int findTheCity(int n, vector<vector<int>>& edges, int distanceThreshold) {

vector w(n, vector<int>(n, INT_MAX / 2)); // 防止加法溢出

for (auto& e: edges) {

int x = e[0], y = e[1], wt = e[2];

w[x][y] = w[y][x] = wt;

}

vector memo(n, vector(n, vector<int>(n)));

auto dfs = [&](this auto&& dfs, int k, int i, int j) -> int {

if (k < 0) { // 递归边界

return w[i][j];

}

auto& res = memo[k][i][j]; // 注意这里是引用

if (res) { // 之前计算过

return res;

}

return res = min(dfs(k - 1, i, j), dfs(k - 1, i, k) + dfs(k - 1, k, j));

};

int ans = 0;

int min_cnt = n;

for (int i = 0; i < n; i++) {

int cnt = 0;

for (int j = 0; j < n; j++) {

if (j != i && dfs(n - 1, i, j) <= distanceThreshold) {

cnt++;

}

}

if (cnt <= min_cnt) { // 相等时取最大的 i

min_cnt = cnt;

ans = i;

}

}

return ans;

}

};

lc2977

tire+floyd+dp

题解

struct Node {

Node* son[26]{};

int sid = -1; // 字符串的编号

};

class Solution {

public:

long long minimumCost(string source, string target, vector<string>& original, vector<string>& changed, vector<int>& cost) {

Node* root = new Node();

int sid = 0;

auto put = [&](string& s) -> int {

Node* o = root;

for (char b: s) {

int i = b - 'a';

if (o->son[i] == nullptr) {

o->son[i] = new Node();

}

o = o->son[i];

}

if (o->sid < 0) {

o->sid = sid++;

}

return o->sid;

};

// 初始化距离矩阵

int m = cost.size();

vector dis(m * 2, vector<int>(m * 2, INT_MAX / 2));

for (int i = 0; i < m * 2; i++) {

dis[i][i] = 0;

}

for (int i = 0; i < m; i++) {

int x = put(original[i]);

int y = put(changed[i]);

dis[x][y] = min(dis[x][y], cost[i]);

}

// Floyd 求任意两点最短路

for (int k = 0; k < sid; k++) {

for (int i = 0; i < sid; i++) {

if (dis[i][k] == INT_MAX / 2) { // 加上这句话,巨大优化!

continue;

}

for (int j = 0; j < sid; j++) {

dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);

}

}

}

int n = source.size();

vector<long long> f(n + 1);

for (int i = n - 1; i >= 0; i--) {

// 不修改 source[i]

f[i] = source[i] == target[i] ? f[i + 1] : LONG_LONG_MAX / 2;

Node* p = root;

Node* q = root;

for (int j = i; j < n; j++) {

p = p->son[source[j] - 'a'];

q = q->son[target[j] - 'a'];

if (p == nullptr || q == nullptr) {

break;

}

if (p->sid < 0 || q->sid < 0) {

continue;

}

// 修改从 i 到 j 的这一段

int d = dis[p->sid][q->sid];

if (d < INT_MAX / 2) {

f[i] = min(f[i], dis[p->sid][q->sid] + f[j + 1]);

}

}

}

return f[0] < LONG_LONG_MAX / 2 ? f[0] : -1;

}

};

相关推荐
独自破碎E2 小时前
【总和拆分 + 双变量遍历】LCR_012_寻找数组的中心下标
数据结构·算法
WBluuue2 小时前
Codeforces 1076 Div3(ABCDEFG)
c++·算法
u0109272712 小时前
模板编译期排序算法
开发语言·c++·算法
GIS瞧葩菜2 小时前
Cesium 轴拖拽 + 旋转圈拖拽 核心数学知识
人工智能·算法·机器学习
m0_686041612 小时前
C++中的适配器模式变体
开发语言·c++·算法
txzrxz2 小时前
结构体排序,双指针,单调栈
数据结构·算法·双指针算法·单调栈·结构体排序
AndrewHZ2 小时前
【AI黑话日日新】什么是AI智能体?
人工智能·算法·语言模型·大模型·llm·ai智能体
wWYy.2 小时前
算法:二叉树最大路径和
数据结构·算法
葱明撅腚2 小时前
利用Python挖掘城市数据
python·算法·gis·聚类