二叉树
P1305 新二叉树
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 310, INF = 0x3f3f3f3f;
char a, b, c, rt, tr[N][2];
int n;
// pre(u) : 先序遍历以 u 为根的子树
void pre(char u) {
if (u == '*')
return;
cout << u; // 遍历 u,即根节点
pre(tr[u][0]); // 遍历 u 的左儿子
pre(tr[u][1]); // 遍历 u 的右儿子
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a >> b >> c;
if (i == 0)
rt = a;
tr[a][0] = b;
tr[a][1] = c;
}
pre(rt);
return 0;
}
B3642 二叉树的遍历
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6, INF = 0x3f3f3f3f;
int n, tr[N][2];
// struct Node {
// int l, r;
// } tree[N]; // 还可以使用结构体封装左右儿子
// pre(u) : 先序遍历以 u 为根的子树
void pre(int u) {
if (u == 0)
return;
cout << u << " "; // 遍历 u,即根节点
pre(tr[u][0]); // 遍历 u 的左儿子
pre(tr[u][1]); // 遍历 u 的右儿子
}
void in(int u) {
if (u == 0)
return;
in(tr[u][0]); // 遍历 u 的左儿子
cout << u << " "; // 遍历 u,即根节点
in(tr[u][1]); // 遍历 u 的右儿子
}
void post(int u) {
if (u == 0)
return;
post(tr[u][0]); // 遍历 u 的左儿子
post(tr[u][1]); // 遍历 u 的右儿子
cout << u << " "; // 遍历 u,即根节点
}
int main() {
cin >> n;
for (int i = 1, l, r; i <= n; i++) {
cin >> l >> r;
tr[i][0] = l, tr[i][1] = r;
}
pre(1), cout << endl;
in(1), cout << endl;
post(1), cout << endl;
return 0;
}
P4913 【深基16.例3】二叉树深度
点击查看代码
#include <bits/stdc++.h> // 万能头
using namespace std;
const int N = 1e6 + 10;
struct T {
int l, r;
} tree[N];
int dfs(int rt) {
if (tree[rt].l == 0 && tree[rt].r == 0) return 1;
return max(dfs(tree[rt].l), dfs(tree[rt].r)) + 1;
}
int main() {
int n;
scanf("%d", &n);
for (int i = 1, l, r; i <= n; i++) {
scanf("%d%d", &l, &r);
tree[i].l = l;
tree[i].r = r;
}
printf("%d\n", dfs(1));
return 0;
}
P3884 [JLOI2009] 二叉树问题
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6, INF = 0x3f3f3f3f;
vector<int> g[N];
int n, v1, v2, v3, dep[N], st[N], p[N];
void dfs(int u, int d) {
dep[u] = d, v1 = max(v1, d), v2 = max(v2, ++st[d]);
for (auto v : g[u]) {
p[v] = u, dfs(v, d + 1);
}
}
int main() {
cin >> n;
int u, v;
for (int i = 1; i <= n; i++) {
cin >> u >> v;
if (i < n) g[u].push_back(v);
}
dfs(1, 1);
// u -> v
int up = 0, down = 0;
while (dep[u] > dep[v]) u = p[u], up++;
while (dep[u] < dep[v]) v = p[v], down++;
while (u != v) u = p[u], v = p[v], up++, down++;
v3 = 2 * up + down;
cout << v1 << endl << v2 << endl << v3 << endl;
return 0;
}
P8681 [蓝桥杯 2019 省 AB] 完全二叉树的权值
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int tr[N], w[N], k, n;
// w[d] :表示深度 d 的所有节点权值和
// dfs(u,d) : 遍历 u为 根节点的子树,深度为 d
void dfs(int u, int d) {
if (u > n) return;
w[d] += tr[u], k = max(k, d);
dfs(2 * u, d + 1);
dfs(2 * u + 1, d + 1);
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &tr[i]); // 建树
dfs(1, 1);
int id = 1; // 节点权值和最大的深度
for (int i = 1; i <= k; i++)
if (w[id] < w[i]) id = i;
printf("%d", id);
return 0;
}
搜索
P1451 求细胞数量
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 110, INF = 0x3f3f3f3f;
int n, m, ans;
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};
string s[N];
bool st[N][N];
void dfs(int x, int y) {
st[x][y] = 1;
for (int i = 0; i < 4; i++) {
int a = x + dx[i];
int b = y + dy[i];
if (a < 0 || a >= n || b < 0 || b >= m) continue;
if (!st[a][b] && s[a][b] != '0') dfs(a, b);
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++)
cin >> s[i];
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (s[i][j] != '0' && !st[i][j])
ans++, dfs(i, j);
cout << ans;
return 0;
}
P1596 [USACO10OCT] Lake Counting S
点击查看代码
P1605 迷宫
点击查看代码
P1706 全排列问题
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 22, INF = 0x3f3f3f3f;
int n;
namespace AC {
void solve() {
int a[N];
for (int i = 1; i <= n; i++)
a[i] = i;
do {
for (int i = 1; i <= n; i++)
cout << setw(5) << a[i];
cout << endl;
} while (next_permutation(a + 1, a + 1 + n));
}
}; // namespace AC
int a[N]; // a[i] 表示编号 i的凳子是谁在坐
bool st[N]; // st[i] 表示编号 i 是否坐下
// dfs(u) : 表示当前的第 u 个位置
void dfs(int u) {
if (u > n) {
for (int i = 1; i <= n; i++) cout << setw(5) << a[i];
cout << endl; return;
}
for (int i = 1; i <= n; i++)
if (!st[i]) { // 当前编号 i 的人还没有坐下
st[i] = 1, a[u] = i, dfs(u + 1); // 编号 i 坐在的第 u个凳子上
st[i] = 0;
}
}
int main() {
cin >> n, dfs(1);
// AC::solve();
return 0;
}
// " \n"[i==n];
// int c = flag ? a : b;
P1157 组合的输出
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 22, INF = 0x3f3f3f3f;
int n, r;
int a[N]; // a[i] 表示编号 i的凳子是谁在坐
bool st[N]; // st[i] 表示编号 i 是否坐下
// dfs(u) : 表示当前的第 u 个位置
void dfs(int u) {
if (u > r) {
for (int i = 1; i <= r; i++)
cout << setw(3) << a[i];
cout << endl;
return;
}
for (int i = 1; i <= n; i++)
if (!st[i] && (u == 1 || a[u - 1] < i)) { // i 可以坐下
st[i] = 1, a[u] = i, dfs(u + 1); // 编号 i 坐在的第 u个凳子上
st[i] = 0;
}
}
int main() {
cin >> n >> r, dfs(1);
return 0;
}
P1036 [NOIP2002 普及组] 选数
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 22, INF = 0x3f3f3f3f;
int n, r, num[N], ans;
int a[N]; // a[i] 表示编号 i的凳子是谁在坐
bool st[N]; // st[i] 表示编号 i 是否坐下
bool isp(int n) {
for (int i = 2; i <= n / i; i++)
if (n % i == 0)
return 0;
return n > 1;
}
// dfs(u) : 表示当前的第 u 个位置
void dfs(int u) {
if (u > r) {
int sum = 0;
for (int i = 1; i <= r; i++) sum += num[a[i]];
if (isp(sum)) ans++;
return;
}
for (int i = 1; i <= n; i++)
if (!st[i] && (u == 1 || a[u - 1] < i)) { // 当前编号 i 的人还没有坐下
st[i] = 1, a[u] = i, dfs(u + 1); // 编号 i 坐在的第 u个凳子上
st[i] = 0;
}
}
int main() {
cin >> n >> r;
for (int i = 1; i <= n; i++) cin >> num[i];
dfs(1), cout << ans;
return 0;
}
P1443 马的遍历
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 410, INF = 0x3f3f3f3f;
int n, m, x, y, st[N][N];
int d[][2] = {-2, -1, -2, 1, -1, -2, -1, 2, 1, -2, 1, 2, 2, -1, 2, 1};
void bfs() {
queue<pair<int, int> > q;
q.push(make_pair(x, y)), st[x][y] = 1;
while (q.size()) {
auto it = q.front(); q.pop();
x = it.first, y = it.second;
for (int i = 0; i < 8; i++) {
int a = x + d[i][0];
int b = y + d[i][1];
if (a < 1 || a > n || b < 1 || b > m || st[a][b]) continue;
q.push({a, b}), st[a][b] = st[x][y] + 1;
}
}
}
int main() {
cin >> n >> m >> x >> y, bfs();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cout << st[i][j] - 1 << " \n"[j == m];
return 0;
}
P1135 奇怪的电梯
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 210, INF = 0x3f3f3f3f;
int n, a, b, k[N], st[N];
int bfs() {
queue<int> q;
q.push(a), st[a] = 1;
while (q.size()) {
auto u = q.front(); q.pop();
if (u == b) return st[u] - 1;
for (int i = 0; i < 2; i++) {
int v = u + k[u] * (i % 2 ? 1 : -1);
if (v > 0 && v <= n && !st[v])
q.push(v), st[v] = st[u] + 1;
}
}
return -1;
}
int main() {
cin >> n >> a >> b;
for (int i = 1; i <= n; i++) cin >> k[i];
cout << bfs();
return 0;
}
P1141 01迷宫
点击查看代码
P1219 [USACO1.5] 八皇后 Checker Challenge
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 27, INF = 0x3f3f3f3f;
int n, cnt;
int a[N]; // a[x]=y 第x行的皇后在 第 y 列
int b[N]; // b[y] 第 y 列是否存在皇后
int c[N]; // c[x+y]
int d[N]; // d[x-y+n]
// dfs(x) 当前在第 x 行放置棋子
void dfs(int x) {
if (x > n) {
++cnt;
if (cnt <= 3)
for (int i = 1; i <= n; i++)
cout << a[i] << " \n"[i == n];
return;
}
for (int y = 1; y <= n; y++) {
if (!b[y] && !c[x + y] && !d[x - y + n]) { // 点(x,y)是否可以放
a[x] = y, b[y] = c[x + y] = d[x - y + n] = 1;
dfs(x + 1);
b[y] = c[x + y] = d[x - y + n] = 0;
}
}
}
int main() {
cin >> n, dfs(1), cout << cnt;
return 0;
}
P1379 八数码难题
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 210, INF = 0x3f3f3f3f;
string a, target = "123804765";
int d[][2] = {-1, 0, 1, 0, 0, -1, 0, 1};
int bfs() {
map<string, int> st;
queue<string> q;
q.push(a), st[a] = 1;
while (q.size()) {
auto u = q.front(); q.pop();
if (u == target) return st[u] - 1;// 目标状态
int p = u.find('0'), x = p / 3, y = p % 3;// 0 在(x,y)处
for (int i = 0; i < 4; i++) {
int a = x + d[i][0], b = y + d[i][1];
if (a < 0 || a >= 3 || b < 0 || b >= 3) continue;
string v(u); swap(v[p], v[a * 3 + b]);// 交换
if (!st[v]) q.push(v), st[v] = st[u] + 1;
}
}
return -1;
}
int main() {
cin >> a, cout << bfs();
return 0;
}
搜索剪枝
P1025 [NOIP2001 提高组] 数的划分
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10, INF = 0x3f3f3f3f;
int n, k, ans;
void dfs(int u, int cnt, int s) {
// 可行性剪枝
if (cnt >= k || s >= n) {
if (cnt == k && s == n) ans++;
return;
}
// 优化搜索顺序
for (int i = u; i >= 1 && s + i * (k - cnt) >= n; i--) {
dfs(i, cnt + 1, s + i);
}
}
int main() {
cin >> n >> k, dfs(n, 0, 0), cout << ans;
return 0;
}
P5194 [USACO05DEC] Scales S
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10, INF = 0x3f3f3f3f;
ll n, c, ans, sum[N];
int a[N];
// 1.dfs(u,s) 当前计划选择砝码 u,已选择和为 s。
// 2.出口: u==0
// 3.递归关系:u-1
void dfs(int u, ll s) {
if (s > c) return; // 可行性剪枝
if (s + sum[u] <= ans) return; // 最优性剪枝
ans = max(ans, s);
if (u == 0) return;
dfs(u - 1, s + a[u]);
dfs(u - 1, s);
}
int main() {
cin >> n >> c;
for (int i = 1; i <= n; i++)
cin >> a[i], sum[i] = sum[i - 1] + a[i];
dfs(n, 0), cout << ans;
return 0;
}
P1434 [SHOI2002] 滑雪
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int n, m, g[N][N], d[][2] = {-1, 0, 1, 0, 0, -1, 0, 1};
int dp[N][N];
int dfs(int x, int y) {
if (dp[x][y]) return dp[x][y];
dp[x][y] = 1;
for (int i = 0; i < 4; i++) {
int a = x + d[i][0], b = y + d[i][1];
if (a < 1 || a > n || b < 1 || b > m || g[a][b] >= g[x][y]) continue;
dp[x][y] = max(dp[x][y], dfs(a, b) + 1);
}
return dp[x][y];
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) cin >> g[i][j];
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) ans = max(ans, dfs(i, j));
cout << ans;
}
P2383 狗哥玩木棒
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int n,m, w[30], k = 0;
bool flag;
void dfs(int step, int l1, int l2, int l3, int l4) {
if (flag || l1 > k || l2 > k || l3 > k || l4 > k) return;
if (step > m) {
if (l1 == l2 && l1 == l3 && l1 == l4) flag = true;
return;
}
dfs(step + 1, l1 + w[step], l2, l3, l4);
dfs(step + 1, l1, l2 + w[step], l3, l4);
dfs(step + 1, l1, l2, l3 + w[step], l4);
dfs(step + 1, l1, l2, l3, l4 + w[step]);
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> m, k = 0;
for (int j = 1; j <= m; j++) cin >> w[j], k += w[j];
sort(w + 1, w + 1 + m, [](int x, int y) { return x > y; });
k /= 4;
flag = false, dfs(1, 0, 0, 0, 0);
cout << (flag ? "yes" : "no") << endl;
}
return 0;
}
P1120 小木棍
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 110, INF = 0x3f3f3f3f;
int n, a[N], len, cnt;
bool st[N];
// dfs(now,length,last)
// 当前正在拼第now根原始木棒,且已经拼出长度length,上次使用的木棒last
bool dfs(int now, int length, int last) {
if (now > cnt) return true;
if (length == len) return dfs(now + 1, 0, 1);
int fail = 0;
for (int i = last; i <= n; i++) {
if (!st[i] && length + a[i] <= len && fail != a[i]) {
st[i] = 1;
if (dfs(now, length + a[i], i + 1)) return true;
st[i] = 0, fail = a[i];
if (length == 0 || length + a[i] == len) return false;
}
}
return false;
}
int main() {
int sum = 0, val = 0; cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i], sum += a[i];
sort(a + 1, a + 1 + n, greater<int>());
for (len = a[n]; len <= sum; len++) {
if (sum % len) continue;
cnt = sum / len;
memset(st, 0, sizeof st);
if (dfs(1, 0, 1)) break;
}
cout << len << endl;
return 0;
}
P1092 [NOIP2004 提高组] 虫食算
点击查看代码
P1032 [NOIP2002 提高组] 字串变换
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10, INF = 0x3f3f3f3f;
string A, B, a, b;
map<pair<string, string>, bool> mp;
map<string, int> st;
void bfs() {
queue<string> q;
q.push(A), st[A] = 1;
while (q.size()) {
auto u = q.front(); q.pop();
if (st[u] > 10) continue;
if (u == B) {
cout << st[u] - 1 << endl; return;
}
for (auto it : mp) {
a = it.first.first, b = it.first.second;
int p = u.find(a);
while (p != -1) {
string v = u;
v.replace(v.begin() + p, v.begin() + p + a.size(), b);
if (!st[v]) st[v] = st[u] + 1, q.push(v);
p = u.find(a, p + a.size());
}
}
}
cout << "NO ANSWER!" << endl;
}
int main() {
cin >> A >> B;
while (cin >> a >> b) mp.insert({make_pair(a, b), 1});
bfs();
return 0;
}
P1019 [NOIP2000 提高组] 单词接龙
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 55;
int n, m, ans;
string s[N];
char start;
int g[N][N], use[N];
void dfs(int u, string str) {
ans = max(ans, (int)str.size());
use[u]++;
for (int i = 0; i < n; i++)
if (g[u][i] && use[i] < 2)
dfs(i, str + s[i].substr(g[u][i]));
use[u]--;
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) cin >> s[i];
cin >> start;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
int a = s[i].size(), b = s[j].size();
for (int k = 1; k < min(a, b); k++)
if (s[i].substr(a - k) == s[j].substr(0, k)) {
g[i][j] = k; break;
}
}
for (int i = 0; i < n; i++)
if (s[i][0] == start) dfs(i, s[i]);
cout << ans;
}
P3958 [NOIP2017 提高组] 奶酪
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10, INF = 0x3f3f3f3f;
ll T, n, m, h, r, d, x[N], y[N], z[N];
bool st[N], flag = 0;
double dist(int p1, int p2) {
return (double)sqrt(pow(x[p1] - x[p2], 2) + pow(y[p1] - y[p2], 2) +
pow(z[p1] - z[p2], 2));
}
namespace AC1 {
// 当前在第 u个空洞
void dfs(int u) {
if (flag || abs(z[u] - h) <= r) {
flag = 1;
return;
}
st[u] = 1;
for (int i = 1; i <= n; i++)
if (!st[i] && dist(u, i) <= d)
dfs(i);
}
void solve() {
flag = 0, memset(st, 0x00, sizeof st);
for (int i = 1; i <= n && !flag; i++)
if (abs(z[i]) <= r)
dfs(i);
}
}; // namespace AC1
namespace AC2 {
struct Node {
ll x, y;
} g[N * N];
int p[N];
int find(int u) {
return u == p[u] ? u : p[u] = find(p[u]);
}
bool solve() {
m = 0;
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
if (dist(i, j) <= d)
g[++m] = {i, j};
for (int i = 0; i <= n; i++)
p[i] = i;
for (int i = 1; i <= m; i++) {
int a = find(g[i].x), b = find(g[i].y);
if (a != b)
p[a] = b;
}
flag = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (abs(z[i] - h) <= r && abs(z[j]) <= r && find(i) == find(j))
return flag = 1;
return 0;
}
}; // namespace AC2
int main() {
cin >> T;
while (T--) {
cin >> n >> h >> r, d = 2 * r;
for (int i = 1; i <= n; i++)
cin >> x[i] >> y[i] >> z[i];
// AC1::solve();
AC2::solve();
cout << (flag ? "Yes" : "No") << endl;
}
return 0;
}
P1040 [NOIP2003 提高组] 加分二叉树
点击查看代码
P1074 [NOIP2009 提高组] 靶形数独
点击查看代码
P2827 [NOIP2016 提高组] 蚯蚓
点击查看代码
T266208 小猫爬山
点击查看代码