atcoder ABC 472 题解

AtCoder ABC 472 题解

A - A

题目描述

给定一个仅由大写英文字母组成的字符串 SSS。

把 SSS 中所有不是 A 的字符都替换成 .,输出得到的新字符串。

约束条件

  • SSS 是长度在 111 到 100100100 之间(含两端)的大写英文字母串。

输入格式

输入从标准输入按以下格式给出:

复制代码
S

输出格式

输出答案。

解题思路

按题意直接遍历字符串:遇到 A 保留,其余字符改成 .。没什么坑。

代码

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

int main()
{
    string s;
    cin >> s;
    // 遍历每个字符,注意用 char& 引用才能直接修改原字符串
    for (char &c : s)
    {
        if (c != 'A')
            c = '.';
    }
    cout << s;
    return 0;
}

B - Break a Stick

题目描述

有一根棍子,上面打了 N−1N-1N−1 个切口,把棍子分成 NNN 段。

从左到右每段的长度依次是 L1,L2,...,LNL_1,L_2,\dots,L_NL1,L2,...,LN。

选择一个切口把棍子折成两根,求两根棍子长度差的绝对值的最小值。

(切口宽度忽略不计,每根棍子的长度是它所含各段长度之和。)

约束条件

  • 2≤N≤1002 \le N \le 1002≤N≤100
  • 1≤Li≤1051 \le L_i \le 10^51≤Li≤105
  • 输入全部为整数。

输入格式

复制代码
N
L1 L2 ... LN

输出格式

输出答案。

解题思路

在第 iii 个切口处折断,左半段是前缀和 ∑k=1iLk\sum_{k=1}^{i} L_k∑k=1iLk,右半段是 sum−cur\text{sum}-\text{cur}sum−cur。

对每个位置 iii,枚举所有切口,取 ∣sum−2×cur∣\left|\text{sum}-2\times\text{cur}\right|∣sum−2×cur∣ 的最小值即可。

(实际上不把最后一个位置也算作切口,因为只有 N−1N-1N−1 个切口;但多算一次对最小值没有影响。本题 N≤100N\le100N≤100,直接暴力也足够。)

代码

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n;
    cin >> n;
    vector<int> a;
    int sum = 0; // 所有段长度之和
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        sum += x;
        a.push_back(x);
    }
    // cur 为当前前缀(左半段)长度,右半段为 sum - cur
    // 差值 = |(sum - cur) - cur| = |sum - 2*cur|
    int ans = 0x3f3f3f3f, cur = 0;
    for (int i = 0; i < a.size(); i++)
    {
        cur += a[i];
        ans = min(ans, abs(sum - cur - cur));
    }
    cout << ans;
    return 0;
}

C - On a Diet

题目描述

高桥君回到老家住了 NNN 天,第 iii 天的点心卡路里为 AiA_iAi。

为了养生,他重复下面的规则:如果最近 MMM 天 内吃掉的点心卡路里总和不超过 KKK,就吃掉这天的点心。

具体地,依次对 i=1,2,...,Ni=1,2,\dots,Ni=1,2,...,N 决定:

  • 假设第 iii 天吃了点心,如果从第 max⁡(i−M+1,1)\max(i-M+1,1)max(i−M+1,1) 天到第 iii 天之间吃掉的点心卡路里总和不超过 KKK,就真的吃;否则不吃。

对每个 iii 判断这天是否吃点心。

约束条件

  • 1≤M≤N≤2×1051 \le M \le N \le 2\times10^51≤M≤N≤2×105
  • 1≤K≤10151 \le K \le 10^{15}1≤K≤1015
  • 1≤Ai≤1091 \le A_i \le 10^91≤Ai≤109

输入格式

复制代码
N M K
A1 A2 ... AN

输出格式

输出 NNN 行,第 iii 行吃则 Yes,不吃则 No

解题思路

维护一个滑动窗口:只统计最近 MMM 天里实际吃掉的点心的卡路里总和。

  • 用队列 q 记录最近 MMM 天窗口内吃掉的日期下标,用 sum 记录这些点心的卡路里总和。
  • 处理第 iii 天时,先把队头里已经滑出窗口(下标 <i−M+1< i-M+1<i−M+1)的点心弹出并减掉。
  • sum + a[i] 不超过 KKK,则吃,把 iii 入队、累加 sum;否则不吃(不入队,不影响窗口)。

代码

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

const int maxn = 2e5 + 10;
queue<int> q; // 记录窗口内"吃掉的"那些天的下标
int n, m, a[maxn];
long long k, sum = 0; // sum 是窗口内已吃点心卡路里总和,会很大,用 long long

int main()
{
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        // 先弹出已经滑出最近 m 天窗口的已吃点心
        while (!q.empty())
        {
            int u = q.front();
            if (u < i - m + 1)
                q.pop(), sum -= a[u];
            else
                break;
        }
        // 看看加上当天是否超过 K,决定吃或不吃
        if (sum + a[i] > k)
        {
            cout << "No\n";
            continue; // 不吃:不入队,不影响 sum
        }
        else
        {
            cout << "Yes\n";
            q.push(i);
            sum += a[i];
        }
    }
    return 0;
}

D - Bomber Mad

题目描述

有一个 HHH 行 WWW 列的网格,每个格子要么是空地 .,要么是炸弹 #

对于空地 (i,j)(i,j)(i,j),如果 iii 行和 jjj 列上都不存在 炸弹,则称它是安全空地

每次可以移动到上下左右相邻的空地(不能走到炸弹上)。求满足以下条件的空地 (i,j)(i,j)(i,j) 的个数:

  • 从 (i,j)(i,j)(i,j) 出发,可以在不超过 KKK 次移动内到达某个安全空地。

约束条件

  • 1≤H,W≤5×1051 \le H,W \le 5\times10^51≤H,W≤5×105,H×W≤5×105H\times W \le 5\times10^5H×W≤5×105
  • 0≤K≤H×W−10 \le K \le H\times W-10≤K≤H×W−1

输入格式

复制代码
H W K
S1
S2
...
SH

输出格式

输出满足条件的空地个数。

解题思路

多源 BFS。

  1. 预处理每行、每列是否含炸弹:rb[i]cb[j]
  2. 把所有"安全空地"(S[i][j]=='.'!rb[i]!cb[j])作为 BFS 起点,初始距离记为 1,全部入队。
  3. BFS 在空地 . 上四方向扩展,距离 +1+1+1;遇到 # 或已访问则跳过。当 dist[u] - 1 == K 时不再往外扩展(已经用掉 KKK 步)。
  4. 最后统计 dist != 0 的格子数。

代码

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

const int maxn = 5e5 + 10;
int dist[maxn]; // dist[idx]:到最近安全空地的最少移动次数 + 1(0 表示未到达)
queue<int> q;

int main()
{
    int h, w;
    long long k;
    cin >> h >> w >> k;
    vector<string> g(h);
    for (int i = 0; i < h; i++)
        cin >> g[i];
    // 预计算每行、每列是否有炸弹,用来找安全空地
    vector<int> rb(h, 0), cb(w, 0);
    for (int i = 0; i < h; i++)
        for (int j = 0; j < w; j++)
            if (g[i][j] == '#')
                rb[i] = cb[j] = 1;
    // 所有安全空地作为多源 BFS 的起点
    for (int i = 0; i < h; i++)
        for (int j = 0; j < w; j++)
            if (g[i][j] == '.' && !rb[i] && !cb[j])
            {
                int idx = i * w + j;
                dist[idx] = 1;
                q.push(idx);
            }
    int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        int x = u / w, y = u % w;
        if (dist[u] - 1 == k) // 已经用掉 k 步,不再扩展
            continue;
        for (int d = 0; d < 4; d++)
        {
            int nx = x + dx[d], ny = y + dy[d];
            if (nx < 0 || nx >= h || ny < 0 || ny >= w)
                continue;
            int v = nx * w + ny;
            if (g[nx][ny] == '#' || dist[v]) // 炸弹或已访问
                continue;
            dist[v] = dist[u] + 1;
            q.push(v);
        }
    }
    int ans = 0;
    for (int i = 0; i < h; i++)
        for (int j = 0; j < w; j++)
            if (dist[i * w + j])
                ans++;
    cout << ans;
    return 0;
}

E - Odd Cycle

题目描述

给定一个 NNN 个点、MMM 条边的简单连通无向图,判断是否存在由奇数个顶点构成的环,如果存在就输出一个。

形式化地说,判断是否存在整数序列 (v1,...,vK)(v_1,\dots,v_K)(v1,...,vK) 满足:

  • K≥3K\ge 3K≥3 且为奇数;
  • v1,...,vKv_1,\dots,v_Kv1,...,vK 互不相同;
  • 对所有 1≤i≤K1\le i\le K1≤i≤K,viv_ivi 与 vi+1v_{i+1}vi+1 之间有边(vK+1=v1v_{K+1}=v_1vK+1=v1)。

有 TTT 个测试用例。

约束条件

  • 1≤T≤2×1051\le T\le 2\times10^51≤T≤2×105
  • 1≤N,M≤2×1051\le N,M\le 2\times10^51≤N,M≤2×105,所有用例的 NNN、MMM 总和均 ≤2×105\le 2\times10^5≤2×105

输入格式

复制代码
T
case1
case2
...
caseT

每个用例:

复制代码
N M
a1 b1
...
aM bM

输出格式

对每个用例,不存在则输出 -1;存在则输出:

复制代码
K
v1 v2 ... vK

解题思路

一个图是二分图当且仅当它不存在奇环。所以用 1,21,21,2 两种颜色做 BFS 染色:

  • col[v] = 3 - col[u] 给未访问的邻点染色,同时记录父节点 par[v]=u 和深度 dep[v]
  • 一旦发现某条边两端颜色相同(col[v]==col[u]),就找到了一个奇环,记下这条边的两端 fu, fv

重建奇环:从 fufv 分别沿 par 往上爬,先对齐深度,再一起往上爬到公共祖先(a==b),把两条路径拼起来,加上原来 fu-fv 的那条边,就得到一条奇环。

代码

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

const int maxn = 2e5 + 10;
int col[maxn], dep[maxn], par[maxn];
queue<int> q;

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        int n, m;
        cin >> n >> m;
        vector<vector<int>> e(n + 1);
        for (int i = 0; i < m; i++)
        {
            int u, v;
            cin >> u >> v;
            e[u].push_back(v);
            e[v].push_back(u);
        }
        // 重置每个用例的状态
        for (int i = 1; i <= n; i++) col[i] = dep[i] = par[i] = 0;
        while (!q.empty()) q.pop();
        q.push(1);
        col[1] = 1;
        int fu = 0, fv = 0; // 两端同色的那条边
        while (!q.empty() && !fu)
        {
            int u = q.front();
            q.pop();
            for (int v : e[u])
            {
                if (!col[v]) // 未染色:染色 + 记录父节点和深度
                {
                    col[v] = 3 - col[u];
                    dep[v] = dep[u] + 1;
                    par[v] = u;
                    q.push(v);
                }
                else if (col[v] == col[u]) // 发现同色边 -> 存在奇环
                {
                    fu = u, fv = v;
                    break;
                }
            }
        }
        if (!fu) // 染色成功,是二分图,无奇环
        {
            cout << "-1\n";
            continue;
        }
        // 从 fu、fv 分别爬父指针,对齐深度后一起爬到公共祖先
        vector<int> pu, pv;
        int a = fu, b = fv;
        while (dep[a] > dep[b]) { pu.push_back(a); a = par[a]; }
        while (dep[b] > dep[a]) { pv.push_back(b); b = par[b]; }
        while (a != b) { pu.push_back(a); pv.push_back(b); a = par[a]; b = par[b]; }
        pu.push_back(a); // 公共祖先
        // 环 = fu 向上的路径 + 公共祖先向下(fv 向上)的路径反向拼回
        vector<int> cyc = pu;
        for (int i = (int)pv.size() - 1; i >= 0; i--) cyc.push_back(pv[i]);
        cout << cyc.size() << "\n";
        for (int x : cyc) cout << x << " ";
        cout << "\n";
    }
    return 0;
}

F - Centroid of a Slice

题目描述

平面上有一个凸 NNN 边形 PPP,顶点按逆时针编号 1,...,N1,\dots,N1,...,N,顶点 iii 的坐标为 (xi,yi)(x_i,y_i)(xi,yi)。

回答 QQQ 个询问。第 jjj 个询问给定两个不相邻的顶点 uj,vju_j,v_juj,vj,用线段把 PPP 分成两个多边形,取从 uju_juj 指向 vjv_jvj 的直线右侧 的那个为 P′P'P′,求 P′P'P′ 的重心(把多边形内部看作均匀薄板时的质心)。

约束条件

  • 4≤N≤3×1044\le N\le 3\times10^44≤N≤3×104,1≤Q≤2×1051\le Q\le 2\times10^51≤Q≤2×105
  • ∣xi∣,∣yi∣≤5×105|x_i|,|y_i|\le 5\times10^5∣xi∣,∣yi∣≤5×105

输入格式

复制代码
N Q
x1 y1
...
xN yN
u1 v1
...
uQ vQ

输出格式

输出 QQQ 行,每行两个数 pj qjp_j\ q_jpj qj,误差不超过 10−610^{-6}10−6 即可。

解题思路

多边形的重心公式:把多边形三角剖分为以原点为参考的三角形,每条有向边 (i,i+1)(i,i+1)(i,i+1) 贡献

cri=xiyi+1−xi+1yicr_i = x_i y_{i+1} - x_{i+1} y_icri=xiyi+1−xi+1yi

然后

Cx=∑(xi+xi+1) cri3∑cri,Cy=∑(yi+yi+1) cri3∑criC_x = \frac{\sum (x_i+x_{i+1})\,cr_i}{3\sum cr_i},\quad C_y = \frac{\sum (y_i+y_{i+1})\,cr_i}{3\sum cr_i}Cx=3∑cri∑(xi+xi+1)cri,Cy=3∑cri∑(yi+yi+1)cri

(逆时针多边形 ∑cri>0\sum cr_i>0∑cri>0,即面积的两倍。)

对于询问 (u,v)(u,v)(u,v),裁剪出的多边形 P′P'P′ 是 PPP 顶点序列中 uuu 到 vvv(沿逆时针的一段)加上弦 v→uv\to uv→u。做法:

  1. 用某个邻点 w=(u mod N)+1w=(u\bmod N)+1w=(umodN)+1 判断弦的方向:根据叉积 cxcxcx 的正负确定 P′P'P′ 是 u→vu\to vu→v 这段还是 v→uv\to uv→u 这段(题目要求的是直线 u→vu\to vu→v 右侧的部分)。
  2. 把顶点复制一遍(x[n+i]=x[i]),用前缀和预处理 ∑cr\sum cr∑cr、∑(xi+xi+1)cr\sum (x_i+x_{i+1})cr∑(xi+xi+1)cr、∑(yi+yi+1)cr\sum (y_i+y_{i+1})cr∑(yi+yi+1)cr,从而 O(1)O(1)O(1) 得到弧上所有边的贡献。
  3. 最后补上弦边 b→ab\to ab→a 的贡献,再用公式求重心。

代码

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

const int maxn = 4e5 + 10;
int n, q;
long long x[maxn], y[maxn];
__int128 P_cr[maxn], P_sx[maxn], P_sy[maxn]; // 前缀和:叉积、x 一阶矩、y 一阶矩

int main()
{
    cin >> n >> q;
    for (int i = 1; i <= n; i++) cin >> x[i] >> y[i];
    // 复制一遍顶点方便跨越 n 的区间取前缀
    for (int i = n + 1; i <= 2 * n + 1; i++) { x[i] = x[i - n]; y[i] = y[i - n]; }
    P_cr[0] = P_sx[0] = P_sy[0] = 0;
    for (int i = 1; i <= 2 * n; i++)
    {
        __int128 cr = (__int128)x[i] * y[i + 1] - (__int128)x[i + 1] * y[i];
        __int128 sx = (__int128)(x[i] + x[i + 1]) * cr;
        __int128 sy = (__int128)(y[i] + y[i + 1]) * cr;
        P_cr[i] = P_cr[i - 1] + cr;
        P_sx[i] = P_sx[i - 1] + sx;
        P_sy[i] = P_sy[i - 1] + sy;
    }
    while (q--)
    {
        int u, v;
        cin >> u >> v;
        int w = (u % n) + 1;
        // 用 u 的下一个顶点判断直线 u->v 的哪一侧,决定取哪段弧
        long long cx = (x[v] - x[u]) * (y[w] - y[u]) - (y[v] - y[u]) * (x[w] - x[u]);
        int a, b;
        if (cx < 0) { a = u; b = v; }
        else { a = v; b = u; }
        int bb = b;
        if (bb <= a) bb += n; // 保证区间 [a, bb-1] 合法
        __int128 tcr = P_cr[bb - 1] - P_cr[a - 1];
        __int128 tsx = P_sx[bb - 1] - P_sx[a - 1];
        __int128 tsy = P_sy[bb - 1] - P_sy[a - 1];
        // 补上弦边 b->a 的贡献
        __int128 cr_c = (__int128)x[b] * y[a] - (__int128)x[a] * y[b];
        tsx += (__int128)(x[b] + x[a]) * cr_c;
        tsy += (__int128)(y[b] + y[a]) * cr_c;
        tcr += cr_c;
        long double Cx = (long double)tsx / (3.0L * (long double)tcr);
        long double Cy = (long double)tsy / (3.0L * (long double)tcr);
        cout << fixed << setprecision(15) << Cx << " " << Cy << "\n";
    }
    return 0;
}

G - Cascading Grid

题目描述

有一个 HHH 行 WWW 列的网格,每个格子上写着 +-# 之一。

你可以进行任意次(含 0 次)操作:

  • 选择一个不是 # 的格子。把从该格子出发,只通过左、右、下 方向的相邻移动、且不经过 # 格子所能到达的所有格子(含自身)都变成 #

操作结束后,求网格中 + 的个数减去 - 的个数所能达到的最大值。

约束条件

  • 1≤H,W≤301\le H,W\le 301≤H,W≤30

输入格式

复制代码
H W
S1
S2
...
SH

输出格式

输出答案。

解题思路

先观察这个"淹没"操作的性质:只能往左、右、下移动,不能向上。因此:

  • 每一行里由 # 分割出的连续非 # 段是一个整体------选其中任意一个格子,整段会被一起变成 #
  • 若某一行的某个段被变成 #,那么它上、下相邻(同列)的段,只要连着的格子是非 #,也会被一起淹没。

于是把每一段的"整段删除/保留"看作一个决策:

  1. 把每个水平段看作一个节点,权重 w=w=w=(段内 + 个数)−-−(段内 - 个数)。
  2. 如果段 AAA 在某个列上位于段 BBB 的正上方且两格都非 #,连一条 B→AB\to AB→A 的有向边------表示"如果段 BBB 被淹没,段 AAA 也无法保留"。
  3. 我们保留的段集合 SSS 必须满足封闭性:若 x∈Sx\in Sx∈S 且存在边 x→yx\to yx→y,则 y∈Sy\in Sy∈S(即保留一个段,其下方的段也必须保留)。目标是最大化 ∑c∈Swc\sum_{c\in S} w_c∑c∈Swc。

这就是经典的最大权闭合子图问题,用最大流求解:

  • 源点 SSS 向所有 wc>0w_c>0wc>0 的段连容量 wcw_cwc 的边;
  • 所有 wc<0w_c<0wc<0 的段向汇点 TTT 连容量 −wc-w_c−wc 的边;
  • 对每条依赖边 x→yx\to yx→y 连容量 +∞+\infty+∞ 的边;
  • 答案 === 正权总和 - 最小割(最大流)。

因为 H,W≤30H,W\le30H,W≤30,段数最多 H×W=900H\times W=900H×W=900,跑 Dinic 足够快。

代码

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

const int maxn = 910;
int H, W;
char g[35][35];
int id[35][35], w[maxn], sccCnt; // 每个水平段一个节点,w 为其净收益(+ 数 - - 数)

struct Edge { int to, nxt; long long cap; };
struct Dinic
{
    Edge e[maxn * 20];
    int head[maxn], cur[maxn], dep[maxn], cnt = 0, S, T, n;
    void init(int n_, int s, int t)
    {
        n = n_; S = s; T = t;
        for (int i = 0; i <= n; i++) head[i] = -1;
        cnt = 0;
    }
    void add(int u, int v, long long c)
    {
        e[cnt] = {v, head[u], c}; head[u] = cnt++;
        e[cnt] = {u, head[v], 0}; head[v] = cnt++;
    }
    bool bfs()
    {
        for (int i = 0; i <= n; i++) dep[i] = 0;
        queue<int> q; q.push(S); dep[S] = 1;
        while (!q.empty())
        {
            int u = q.front(); q.pop();
            for (int i = head[u]; ~i; i = e[i].nxt)
            {
                int v = e[i].to;
                if (e[i].cap && !dep[v]) { dep[v] = dep[u] + 1; q.push(v); }
            }
        }
        return dep[T];
    }
    long long dfs(int u, long long f)
    {
        if (u == T || !f) return f;
        long long s = 0;
        for (int &i = cur[u]; ~i; i = e[i].nxt)
        {
            int v = e[i].to;
            if (e[i].cap && dep[v] == dep[u] + 1)
            {
                long long d = dfs(v, min(f, e[i].cap));
                e[i].cap -= d; e[i ^ 1].cap += d; s += d; f -= d;
                if (!f) break;
            }
        }
        return s;
    }
    long long flow()
    {
        long long r = 0;
        while (bfs()) { for (int i = 0; i <= n; i++) cur[i] = head[i]; r += dfs(S, 1e18); }
        return r;
    }
} din;

int main()
{
    cin >> H >> W;
    for (int i = 1; i <= H; i++) { string s; cin >> s; for (int j = 1; j <= W; j++) g[i][j] = s[j - 1]; }

    // 划分水平段:同一行内由 # 分隔的连续非 # 格子视为一个节点
    for (int i = 1; i <= H; i++)
    {
        int j = 1;
        while (j <= W)
        {
            if (g[i][j] == '#') { j++; continue; }
            sccCnt++;
            while (j <= W && g[i][j] != '#')
            {
                id[i][j] = sccCnt;
                w[sccCnt] += (g[i][j] == '+' ? 1 : -1);
                j++;
            }
        }
    }

    int S = sccCnt + 1, T = sccCnt + 2;
    din.init(T, S, T);
    // 最大权闭合子图:源 -> 正权,负权 -> 汇
    long long pos = 0;
    for (int c = 1; c <= sccCnt; c++)
    {
        if (w[c] > 0) { din.add(S, c, w[c]); pos += w[c]; }
        else if (w[c] < 0) din.add(c, T, -w[c]);
    }

    // 依赖边:下段 -> 上段(保留下段必须保留上段)
    set<pair<int, int>> es;
    for (int i = 1; i < H; i++)
        for (int j = 1; j <= W; j++)
            if (g[i][j] != '#' && g[i + 1][j] != '#')
            {
                int u = id[i][j], v = id[i + 1][j];
                if (u != v) es.insert({v, u}); // v 在下,u 在上:v -> u
            }
    for (auto &p : es) din.add(p.first, p.second, 1e18);

    cout << pos - din.flow(); // 最大权 = 正权总和 - 最小割
    return 0;
}
相关推荐
AI服务老曹1 小时前
抽烟识别算法接入 AI 视频分析平台的流程与误报优化指南
人工智能·算法·音视频
阳明山水1 小时前
销量预测2025—2026:技术演进、实证发现与系统架构的系统性综述
人工智能·深度学习·算法·机器学习·架构
伯远医学1 小时前
RIP-seq 高分文献案例分享
java·前端·javascript·人工智能·算法·eclipse·html
张张的快乐时光呀!1 小时前
MFC添加类向导并实现响应
c++·mfc
啊嘞嘞?2 小时前
力扣(LRU缓存)
算法·leetcode
珂朵莉MM2 小时前
2026国信杯具身智能创新大赛-编程技能赛--本科组国赛解题报告 | 珂学家
算法·深度优先·图论
啊嘞嘞?2 小时前
力扣(下一个排列)
算法·leetcode
程与留2 小时前
09_Qt 布局管理系统——QHBoxLayout、QVBoxLayout、QGridLayout
c++·qt
神仙别闹2 小时前
基于QT(C++)实现旅游线路规划系统
c++·qt·旅游