BFS · 贪心 · 动态规划入门 · 图论入门 · 并查集与最小生成树 · 刷题路线图
BFS 与 DFS 的区别:DFS 是"一条路走到黑",BFS 是"一层一层扩"。求最短步数一律优先想 BFS。
struct Node{ int x, y, d; }; // 坐标 + 步数
int bfs(int sx, int sy, int tx, int ty) {
queue<Node> q;
q.push({sx, sy, 0}); vis[sx][sy] = true;
while (!q.empty()) {
Node u = q.front(); q.pop();
if (u.x == tx && u.y == ty) return u.d;
for (int k = 0; k < 4; k++) {
int nx = u.x + dx[k], ny = u.y + dy[k];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny]) {
vis[nx][ny] = true;
q.push({nx, ny, u.d + 1});
}
}
}
return -1;
}
priority_queue 维护。典型:合并果子、任务调度。// 活动安排:最多能参加几个活动
struct A{ int s, e; };
bool cmp(const A&a, const A&b){ return a.e < b.e; } // 按结束时间排序
int cnt = 0, last = -1;
for (auto &x : a)
if (x.s >= last) { cnt++; last = x.e; }
cout << cnt << endl;
贪心最大的坑是"局部最优 ≠ 全局最优"(例如普通硬币找零)。写之前想一个反例;举不出反例再提交。
dp[...] 表示什么(用一句话说清楚)// 0-1 背包:容量 V,n 件物品,取或不取,价值最大
int dp[1005] = {0};
for (int i = 1; i <= n; i++)
for (int v = V; v >= w[i]; v--) // 逆序!保证每件只用一次
dp[v] = max(dp[v], dp[v-w[i]] + c[i]);
cout << dp[V] << endl;
// 邻接表
vector<int> g[100005]; // g[u] 存 u 的所有邻居
g[u].push_back(v); g[v].push_back(u); // 无向边
// 带权:vector<pair<int,int>> g[]; 存 (邻居, 边权)
// Dijkstra 核心(堆优化)
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;
dis[s] = 0; pq.push({0, s});
while (!pq.empty()) {
auto [d, u] = pq.top(); pq.pop();
if (d > dis[u]) continue;
for (auto [v, w] : g[u])
if (dis[u] + w < dis[v]) { dis[v] = dis[u] + w; pq.push({dis[v], v}); }
}
// 并查集(路径压缩)——控制"谁和谁是一伙的"
int fa[100005];
int find(int x){ return fa[x] == x ? x : fa[x] = find(fa[x]); }
void merge(int a, int b){ fa[find(a)] = find(b); }
// 初始化:for (int i = 1; i <= n; i++) fa[i] = i;
// 判环:若 find(u) == find(v) 说明 u、v 已经连通,再加边就成环