20230530 solution ( tree_a + tree_c + weight + boxes )
T1
关键是看懂题目 题中说邻接表存储 说明第i组应该对应的就是第i个节点的信息
然后就是个普通的中序遍历了
code:
#include <bits/stdc++.h>
using namespace std;
const int N = 520;
int ls[N], rs[N], val[N];
int n, tar, cnt;
void dfs(int x) {
if (ls[x] != 0) dfs(ls[x]);
++cnt;
if (val[x] == tar) printf("%d\n",cnt);
if (rs[x] != 0) dfs(rs[x]);
}
int main() {
scanf("%d%d", &n, &tar);
for (int i = 1; i <= n; ++i) scanf("%d%d%d", &val[i], &ls[i], &rs[i]);
dfs(1);
return 0;
}
T2
顺序遍历给出 注意到实际字母只要不是#号是啥不重要
直接开个vis数组存节点空不空就行
然后用dfs来check
code:
#include <bits/stdc++.h>
#define ls (k << 1)
#define rs (k << 1 | 1)
using namespace std;
const int N = 1e6 + 0721;
bool vis[N];
char s[N];
int len;
bool flag = 1;
void dfs(int k) {
if ((vis[ls] && vis[rs]) || (!vis[ls] && !vis[rs])) {
if (vis[ls]) {
dfs(ls);
dfs(rs);
}
}
else {
flag = 0;
return;
}
}
int main() {
scanf("%s", s);
len = strlen(s);
for (int i = 0; i < len; ++i) {
if (s[i] != '#') vis[i + 1] = 1;
}
dfs(1);
if (flag) printf("Yes");
else printf("No");
return 0;
}
T3
类似多重背包的转移
好像没法优化 只能枚举数量
复杂度 O(mns)
code:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 0721;
int c[7];
int val[7] = {0,1,2,3,5,10,20};
bool f[N], g[N];
int main() {
for (int i = 1; i <= 6; ++i) scanf("%d", &c[i]);
f[0] = 1;
for (int i = 1; i <= 6; ++i) {
memcpy(g, f, sizeof f );
for (int j = 1; j <= 1000; ++j) {
for (int k = 1; k <= c[i]; ++k) {
if (j - k * val[i] >= 0) {
if (g[j - k * val[i]]) f[j] = 1;
}
}
}
}
int tot = 0;
for (int i = 1; i <= 1000; ++i) if (f[i]) ++tot;
printf("Total=%d",tot);
return 0;
}
T4
与上题相似 01背包转移
最后倒着往前扫一遍找最近的答案就行了
复杂度 O(mn)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e4 + 0721;
bool f[N], g[N];
int w[N];
int v, n;
int main() {
scanf("%d%d", &v, &n);
for (int i = 1; i <= n; ++i) scanf("%d", &w[i]);
f[0] = 1;
for (int i = 1; i <= n; ++i) {
memcpy(g, f, sizeof f );
for (int j = w[i]; j <= v; ++j) {
if (g[j - w[i]]) f[j] = 1;
}
}
for (int i = v; i >= 0; --i) {
if (f[i]) {
printf("%d",v - i);
break;
}
}
return 0;
}