Skip to content

Commit e196887

Browse files
committed
Add problems G, I, and J for contest 132781; update nowcoderac.json with new problem details
1 parent 041632b commit e196887

29 files changed

Lines changed: 2610 additions & 32 deletions

.obsidian/workspace.json

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -196,22 +196,35 @@
196196
},
197197
"active": "c8b38f4e71e9a4fd",
198198
"lastOpenFiles": [
199-
"acwing/problems/75.和为S的两个数字.cpp",
199+
"niuke/contest/132781/E.md",
200+
"niuke/contest/132781/D.py",
201+
"niuke/contest/132781/G.py",
202+
"niuke/contest/132781/G.md",
203+
"niuke/contest/132781/D.md",
204+
"niuke/contest/132781/J.md",
205+
"niuke/contest/132781/I.md",
206+
"niuke/contest/132781/F.md",
207+
"niuke/contest/132781/C.py",
208+
"niuke/contest/132781/C.md",
209+
"niuke/contest/132781/B.py",
210+
"niuke/contest/132781/B.md",
211+
"niuke/contest/132781/A.py",
212+
"niuke/contest/132781/A.md",
213+
"niuke/contest/132781/nowcoderac.json",
214+
"niuke/contest/132781",
215+
"acwing/problems/3205.最优配餐.md",
216+
"acwing/problems/3205.最优配餐 copy.cpp",
217+
"acwing/problems/3205.最优配餐.cpp",
218+
"acwing/problems/3204.字符串匹配.md",
219+
"acwing/problems/3204.字符串匹配 copy.cpp",
220+
"acwing/problems/3203.画图.md",
221+
"acwing/problems/3202.相邻数对.md",
222+
"acwing/problems/CCF/第一届CCF计算机软件能力认证题解.md",
200223
"acwing/problems/73.数组中只出现一次的两个数字.md",
201224
"acwing/problems/74.md",
202225
"Excalidraw/Drawing 2026-05-06 12.58.59.excalidraw.md",
203226
"acwing/problems/74.数组中唯一只出现一次的数字.md",
204227
"conflict-files-obsidian-git.md",
205-
"Excalidraw",
206-
"niuke/problems/编程入门-C/CPP2.实现四舍五入.cpp",
207-
"niuke/problems/牛客题霸-python入门到实践四十招/NP99.修改属性2.py",
208-
"niuke/problems/牛客题霸-python入门到实践四十招/NP98.修改属性1.py",
209-
"niuke/problems/牛客题霸-python入门到实践四十招/NP97.班级管理.py",
210-
"niuke/problems/牛客题霸-python入门到实践四十招/NP96.球的表面积.py",
211-
"niuke/problems/牛客题霸-python入门到实践四十招/NP95.兔子的数量.py",
212-
"niuke/problems/牛客题霸-python入门到实践四十招/NP94.函数求差.py",
213-
"niuke/problems/牛客题霸-python入门到实践四十招/NP93.创建集合.py",
214-
"niuke/problems/牛客题霸-python入门到实践四十招/NP92.公式计算器.py",
215228
"计算机组成原理/实验5/实验五_任务指导书.md",
216229
"计算机组成原理/实验5/实验五_详细步骤说明.md",
217230
"计算机组成原理/实验5/实验五_完整实验报告.md"

acwing/problems/3200.无线网络.cpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @Author: tkzzzzzz6
33
* @Date: 2026-05-11 15:07:55
44
* @LastEditors: tkzzzzzz6
5-
* @LastEditTime: 2026-05-11 19:11:02
5+
* @LastEditTime: 2026-05-11 19:33:28
66
*/
77
/*
88
* @acwing app=acwing.cn id=3203 lang=C++
@@ -11,6 +11,7 @@
1111
*/
1212

1313
// @acwing code start
14+
// 图论最短路问题
1415
#include <algorithm>
1516
#include <cstring>
1617
#include <iostream>
@@ -24,23 +25,27 @@ using namespace std;
2425
typedef long long ll;
2526
typedef pair<int, int> PII;
2627

27-
const int N = 210, M = N * N;
28+
const int N = 210, M = N * N; // n+m 最多 200个节点,最多 M 个边
2829
int n, m, k, r;
29-
int h[N], e[M], ne[M], idx;
30-
PII p[M];
31-
int dist[N][N];
30+
// h[N] // h[i] = 节点i的邻接表头指针(初值-1表示无邻接)
31+
// e[M] // e[j] = 第j条边指向的目标节点
32+
// ne[M] // ne[j] = 第j条边之后的下一条边的索引(形成链表)
33+
// idx // 当前边的编号计数器
34+
int h[N], e[M], ne[M], idx; // 邻接表存储图
35+
PII p[N]; // 存储所有路由器坐标
36+
int dist[N][N]; // dist[x][y]:到路由器x用y个新路由器的最少步数
3237

3338
bool check(PII a, PII b) {
34-
int dx = a.x - b.x;
35-
int dy = a.y - b.y;
36-
return dx * dx + dy * dy <= r * r;
39+
ll dx = a.x - b.x;
40+
ll dy = a.y - b.y;
41+
return dx * dx + dy * dy <= (ll)r * r;
3742
}
3843

3944
void add(int a, int b) {
4045
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
4146
}
4247

43-
int bfs() {
48+
int bfs() {
4449
queue<PII> q;
4550
q.push({1, 0});
4651
memset(dist, 0x3f, sizeof dist);
@@ -50,11 +55,13 @@ int bfs() {
5055
auto t = q.front();
5156
q.pop();
5257

53-
for (int i = h[t.x]; ~i; i = ne[i]) {
54-
int x = e[i], y = t.y;
55-
if (x > n)
58+
// 遍历路由器 t.x 的所有邻接节点
59+
for (int i = h[t.x]; i != -1; i = ne[i]) { // i != -1 等价于 ~i 因为 -1 == ...1111, ~(-1) == ...0000 = 0
60+
int x = e[i]; //下一个节点
61+
int y = t.y; //继承当前使用的新路由器数
62+
if (x > n) // 下一节点是新增路由器
5663
++y;
57-
if (y <= k) {
64+
if (y <= k) { //不超过 k 个新路由器
5865
if (dist[x][y] > dist[t.x][t.y] + 1) {
5966
dist[x][y] = dist[t.x][t.y] + 1;
6067
q.push({x, y});
@@ -65,21 +72,22 @@ int bfs() {
6572

6673
int res = 1e8;
6774
for (int i = 0; i <= k; ++i) {
68-
res = min(res, dist[2][i]);
75+
res = min(res, dist[2][i]); // 路由器 2 处,用 0~k个新路由器的最少步数
6976
}
70-
return res - 1;
77+
return res - 1; //因为这里求的中转数,步数 - 1 == 中转数
7178
}
7279

7380
int main() {
7481
cin >> n >> m >> k >> r;
7582
memset(h, -1, sizeof h);
83+
// 存储节点
7684
for (int i = 1; i <= n; ++i)
7785
cin >> p[i].x >> p[i].y;
7886
for (int i = n + 1; i <= n + m; ++i)
7987
cin >> p[i].x >> p[i].y;
8088

81-
for (int i = 1; i <= n; ++i) {
82-
for (int j = n + 1; j <= n + m; ++j)
89+
for (int i = 1; i <= n+m; ++i) {
90+
for (int j = i + 1; j <= n + m; ++j)
8391
if (check(p[i], p[j]))
8492
add(i, j), add(j, i);
8593
}

acwing/problems/3200.无线网络.md

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @Author: tkzzzzzz6
33
* @Date: 2026-05-11 15:07:55
44
* @LastEditors: tkzzzzzz6
5-
* @LastEditTime: 2026-05-11 18:47:31
5+
* @LastEditTime: 2026-05-11 19:56:00
66
-->
77

88
目前在一个很大的平面房间里有 $n$ 个无线路由器,每个无线路由器都固定在某个点上。
@@ -58,9 +58,109 @@ $1 \leq r \leq 10^{8}$
5858
```
5959

6060
## 思路:BFS
61-
时间复杂度:
62-
空间复杂度:
61+
时间复杂度:O(k*(n+m)^2)
62+
空间复杂度:O(n*m)
63+
64+
65+
目标:从路由器 1 到路由器 2 的且`不同特殊点数 <= k`的最短路径
66+
67+
等价于:
68+
69+
从路由器 1 到路由器 2 的且`特殊点数 <= k`的最短路径,因为路径出现了环,肯定不是最短路径
70+
6371

6472
DP问题可以看做特殊的图问题(拓扑图问题)
6573

66-
什么是循环依赖:
74+
### 什么是拓扑图?
75+
拓扑图是指一个有向无环图(DAG),其中的节点表示任务或事件,边表示任务之间的依赖关系。在拓扑图中,如果存在一条从节点 A 到节点 B 的路径,那么 A 必须在 B 之前完成。这种结构常用于表示任务调度、编译顺序等问题。
76+
77+
在 DP 问题中,我们可以将状态转移关系表示为一个拓扑图,其中节点表示 DP 状态,边表示状态之间的转移关系。通过对这个拓扑图进行遍历,我们可以按照依赖关系计算出最终的 DP 结果。
78+
79+
### 什么是循环依赖?
80+
循环依赖是指在一个系统中,两个或多个组件相互依赖,形成一个闭环。这种情况会导致系统无法正常运行,因为每个组件都需要另一个组件的输出才能完成自己的功能,但又无法得到所需的输入。
81+
82+
```cpp
83+
#include <algorithm>
84+
#include <cstring>
85+
#include <iostream>
86+
#include <queue>
87+
88+
#define x first
89+
#define y second
90+
91+
using namespace std;
92+
93+
typedef long long ll;
94+
typedef pair<int, int> PII;
95+
96+
const int N = 210, M = N * N; // n+m 最多 200个节点,最多 M 个边
97+
int n, m, k, r;
98+
// h[N] // h[i] = 节点i的邻接表头指针(初值-1表示无邻接)
99+
// e[M] // e[j] = 第j条边指向的目标节点
100+
// ne[M] // ne[j] = 第j条边之后的下一条边的索引(形成链表)
101+
// idx // 当前边的编号计数器
102+
int h[N], e[M], ne[M], idx; // 邻接表存储图
103+
PII p[N]; // 存储所有路由器坐标
104+
int dist[N][N]; // dist[x][y]:到路由器x用y个新路由器的最少步数
105+
106+
bool check(PII a, PII b) {
107+
ll dx = a.x - b.x;
108+
ll dy = a.y - b.y;
109+
return dx * dx + dy * dy <= (ll)r * r;
110+
}
111+
112+
void add(int a, int b) {
113+
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
114+
}
115+
116+
int bfs() {
117+
queue<PII> q;
118+
q.push({1, 0});
119+
memset(dist, 0x3f, sizeof dist); //按字节赋值实际为 0x3f3f3f3f
120+
dist[1][0] = 0;
121+
122+
while (q.size()) {
123+
auto t = q.front();
124+
q.pop();
125+
126+
// 遍历路由器 t.x 的所有邻接节点
127+
for (int i = h[t.x]; i != -1; i = ne[i]) { // i != -1 等价于 ~i 因为 -1 == ...1111, ~(-1) == ...0000 = 0
128+
int x = e[i]; //下一个节点
129+
int y = t.y; //继承当前使用的新路由器数
130+
if (x > n) // 下一节点是新增路由器
131+
++y;
132+
if (y <= k) { //不超过 k 个新路由器
133+
if (dist[x][y] > dist[t.x][t.y] + 1) {
134+
dist[x][y] = dist[t.x][t.y] + 1;
135+
q.push({x, y});
136+
}
137+
}
138+
}
139+
}
140+
141+
int res = 1e8;
142+
for (int i = 0; i <= k; ++i) {
143+
res = min(res, dist[2][i]); // 路由器 2 处,用 0~k个新路由器的最少步数
144+
}
145+
return res - 1; //因为这里求的中转数,步数 - 1 == 中转数
146+
}
147+
148+
int main() {
149+
cin >> n >> m >> k >> r;
150+
memset(h, -1, sizeof h);
151+
// 存储节点
152+
for (int i = 1; i <= n; ++i)
153+
cin >> p[i].x >> p[i].y;
154+
for (int i = n + 1; i <= n + m; ++i)
155+
cin >> p[i].x >> p[i].y;
156+
157+
for (int i = 1; i <= n+m; ++i) {
158+
for (int j = i + 1; j <= n + m; ++j)
159+
if (check(p[i], p[j]))
160+
add(i, j), add(j, i);
161+
}
162+
163+
cout << bfs() << endl;
164+
return 0;
165+
}
166+
```
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* @acwing app=acwing.cn id=3204 lang=C++
3+
*
4+
* 3201. 任务调度
5+
*/
6+
7+
// @acwing code start
8+
#include <algorithm>
9+
#include <cmath>
10+
#include <cstring>
11+
#include <iostream>
12+
13+
using namespace std;
14+
15+
const int N = 50, M = 210, INF = 0x3f3f3f3f;
16+
// c[i][0]: 任务 i 用 1 个 CPU 的耗时 a_i
17+
// c[i][1]: 任务 i 用 1 个 CPU + GPU 的耗时 c_i
18+
// c[i][2]: 任务 i 使用 GPU 时的最优耗时 min(b_i, d_i)
19+
int c[N][3];
20+
// f[cur][i][j][k]: 处理到当前任务时,三类资源累计时间分别为 i,j,k 的最小“额外代价”
21+
// 这里用滚动数组,cur 只有 0/1 两层
22+
int f[2][M][M][M];
23+
24+
int main() {
25+
int n; // 任务数量
26+
cin >> n;
27+
int m = 0, m2 = 0; // m: a_i 总和上界, m2: 奇数下标任务的 a_i 和(用于压缩上界)
28+
for (int i = 1; i <= n; ++i) {
29+
int x, y, z, t; // 输入的 a_i, b_i, c_i, d_i
30+
cin >> x >> y >> z >> t;
31+
c[i][0] = x, c[i][1] = z, c[i][2] = min(y, t);
32+
m += x;
33+
if (i % 2)
34+
m2 += x;
35+
}
36+
m = max(m2, m - m2); // 这里简单得按奇偶性分成两组即可
37+
memset(f, 0x3f, sizeof f);
38+
f[0][0][0][0] = 0;
39+
40+
for (int u = 1; u <= n; ++u) { // 枚举任务编号
41+
for (int i = 0; i <= m; ++i) {
42+
for (int j = 0; j <= m; ++j) {
43+
for (int k = 0; k <= m; ++k) {
44+
int &v = f[u & 1][i][j][k]; // 当前层状态引用
45+
if (k > j)
46+
v = INF;
47+
else {
48+
register int x = c[u][0], y = c[u][1], z = c[u][2], t = (u - 1) & 1;
49+
// t: 上一层滚动数组下标
50+
// x,y,z: 当前任务在不同资源方案下的耗时参数
51+
v = f[t][i][j][k] + z;
52+
if (i >= x)
53+
v = min(v, f[t][i - x][j][k]);
54+
if (j >= x)
55+
v = min(v, f[t][i][j - x][k]);
56+
if (i >= y && k >= y)
57+
v = min(v, f[t][i - y][j][k - y]);
58+
if (j >= y && k >= y)
59+
v = min(v, f[t][i][j - y][k - y]);
60+
}
61+
}
62+
}
63+
}
64+
}
65+
66+
int res = INF; // 最终最小完工时间
67+
for (int i = 0; i <= m; ++i)
68+
for (int j = 0; j <= m; ++j)
69+
for (int k = 0; k <= m; ++k)
70+
res = min(res, f[n & 1][i][j][k] + max(i, max(j, k)));
71+
72+
cout << res << endl;
73+
74+
return 0;
75+
}
76+
77+
// @acwing code end

0 commit comments

Comments
 (0)