当前位置:首页 » 《随便一记》 » 正文

Levoj2023全题目AC破解

28 人参与  2023年04月10日 17:45  分类 : 《随便一记》  评论

点击全文阅读


如有WA全是多组输入问题,请自行修改,或在评论区向我反馈,我会及时修改,如有注释不够详细等问题,也可联系我进行修改:

P1138 American Heritage

C++:

#include <iostream>#include <string>using namespace std;string inorder, preorder; // 前序遍历和中序遍历void postorder(int in_start, int in_end, int pre_start, int pre_end) {    if (in_start > in_end) { // 如果起点大于终点,说明没有子树需要构造        return;    }    // 根节点为前序遍历的第一个节点    char root = preorder[pre_start];    // 在中序遍历中找到根节点的位置    int root_pos = inorder.find(root);    // 递归构建左子树,in_start到root_pos-1为左子树的中序遍历,pre_start+1到pre_start+1+root_pos-in_start-1为左子树的前序遍历    postorder(in_start, root_pos - 1, pre_start + 1, pre_start + 1 + root_pos - in_start - 1);    // 递归构建右子树,root_pos+1到in_end为右子树的中序遍历,pre_start+1+root_pos-in_start到pre_end为右子树的前序遍历    postorder(root_pos + 1, in_end, pre_start + 1 + root_pos - in_start, pre_end);    // 输出当前节点    cout << root;}int main() {    cin >> inorder >> preorder; // 输入中序遍历和前序遍历    postorder(0, inorder.size() - 1, 0, preorder.size() - 1); // 构造二叉树并输出后序遍历    cout << endl;    return 0;}

C:

#include <stdio.h>#include <string.h>#define MAX_N 26char inorder[MAX_N + 1], preorder[MAX_N + 1]; // 前序遍历和中序遍历void postorder(int in_start, int in_end, int pre_start, int pre_end) {    if (in_start > in_end) { // 如果起点大于终点,说明没有子树需要构造        return;    }    // 根节点为前序遍历的第一个节点    char root = preorder[pre_start];    // 在中序遍历中找到根节点的位置    int root_pos = strchr(inorder, root) - inorder;    // 递归构建左子树,in_start到root_pos-1为左子树的中序遍历,pre_start+1到pre_start+1+root_pos-in_start-1为左子树的前序遍历    postorder(in_start, root_pos - 1, pre_start + 1, pre_start + 1 + root_pos - in_start - 1);    // 递归构建右子树,root_pos+1到in_end为右子树的中序遍历,pre_start+1+root_pos-in_start到pre_end为右子树的前序遍历    postorder(root_pos + 1, in_end, pre_start + 1 + root_pos - in_start, pre_end);    // 输出当前节点    printf("%c", root);}int main() {    scanf("%s%s", inorder, preorder); // 输入中序遍历和前序遍历    postorder(0, strlen(inorder) - 1, 0, strlen(preorder) - 1); // 构造二叉树并输出后序遍历    printf("\n");    return 0;}

P1220 皇后摆放问题

C++:

#include <iostream>#include <vector>using namespace std;const int N = 8;vector<int> pos(N); // 记录皇后在每一行的位置int res = 0; // 记录摆放的种类数bool is_valid(int row, int col) {    for (int i = 0; i < row; i++) { // 遍历前面的行,看是否有冲突        if (pos[i] == col || pos[i] - i == col - row || pos[i] + i == col + row) {            return false; // 冲突        }    }    return true; // 不冲突}void backtrack(int row) {    if (row == N) { // 找到一种合法摆法        res++;        return;    }    for (int col = 0; col < N; col++) {        if (is_valid(row, col)) { // 如果当前位置合法,则放置皇后            pos[row] = col;            backtrack(row + 1); // 递归放置下一行的皇后        }    }}int main() {    int cnt = 0;    for (int i = 0; i < N; i++) {        for (int j = 0; j < N; j++) {            int x;            cin >> x;            if (x == 1) { // 已经有皇后了                pos[cnt++] = j; // 记录位置            }        }    }    backtrack(cnt); // 从第 cnt 行开始回溯    cout << res << endl; // 输出摆法的种类数    return 0;}

C:

#include <stdio.h>#include <stdbool.h>#define N 8int pos[N]; // 记录皇后在每一行的位置int res = 0; // 记录摆放的种类数bool is_valid(int row, int col) {    for (int i = 0; i < row; i++) { // 遍历前面的行,看是否有冲突        if (pos[i] == col || pos[i] - i == col - row || pos[i] + i == col + row) {            return false; // 冲突        }    }    return true; // 不冲突}void backtrack(int row) {    if (row == N) { // 找到一种合法摆法        res++;        return;    }    for (int col = 0; col < N; col++) {        if (is_valid(row, col)) { // 如果当前位置合法,则放置皇后            pos[row] = col;            backtrack(row + 1); // 递归放置下一行的皇后        }    }}int main() {    int cnt = 0;    for (int i = 0; i < N; i++) {        for (int j = 0; j < N; j++) {            int x;            scanf("%d", &x);            if (x == 1) { // 已经有皇后了                pos[cnt++] = j; // 记录位置            }        }    }    backtrack(cnt); // 从第 cnt 行开始回溯    printf("%d\n", res); // 输出摆法的种类数    return 0;}

P1236 夺取宝藏

C++:

#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 1010;int a[N][N]; // 保存宝藏的价值int f[N][N]; // f[i][j]表示从左上角走到(i, j)时能够得到的最大价值int main() {    int m, n;    while (cin >> m >> n) {        memset(f, 0, sizeof f); // 初始化f数组为0        for (int i = 1; i <= m; i++) {            for (int j = 1; j <= n; j++) {                cin >> a[i][j];            }        }        for (int i = 1; i <= m; i++) {            for (int j = 1; j <= n; j++) {                f[i][j] = max(f[i - 1][j], f[i][j - 1]) + a[i][j]; // 动态转移方程            }        }        cout << f[m][n] << endl; // 输出最大价值之和    }    return 0;}

C:

#include <stdio.h>#include <string.h>#include <stdlib.h>#define N 1010int a[N][N]; // 保存宝藏的价值int f[N][N]; // f[i][j]表示从左上角走到(i, j)时能够得到的最大价值int main() {    int m, n;    while (scanf("%d%d", &m, &n) != EOF) {        memset(f, 0, sizeof f); // 初始化f数组为0        for (int i = 1; i <= m; i++) {            for (int j = 1; j <= n; j++) {                scanf("%d", &a[i][j]);            }        }        for (int i = 1; i <= m; i++) {            for (int j = 1; j <= n; j++) {                f[i][j] = f[i - 1][j] > f[i][j - 1] ? f[i - 1][j] : f[i][j - 1];                f[i][j] += a[i][j]; // 动态转移方程            }        }        printf("%d\n", f[m][n]); // 输出最大价值之和    }    return 0;}

P1268 连续子段的最大和

C++:

#include <iostream>#include <algorithm>using namespace std;const int N = 10010;int a[N], f[N];int main() {    int n;    cin >> n;    for (int i = 1; i <= n; i++) {        cin >> a[i];    }    int res = a[1]; // 初始化res为第一个数    f[1] = a[1]; // 初始化f[1]为第一个数    for (int i = 2; i <= n; i++) {        f[i] = max(f[i - 1] + a[i], a[i]); // 动态转移方程        res = max(res, f[i]); // 更新最大值    }    cout << res << endl; // 输出子段的最大和    return 0;}

C:

#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 10010int a[N], f[N];int main() {    int n;    scanf("%d", &n);    for (int i = 1; i <= n; i++) {        scanf("%d", &a[i]);    }    int res = a[1]; // 初始化res为第一个数    f[1] = a[1]; // 初始化f[1]为第一个数    for (int i = 2; i <= n; i++) {        f[i] = f[i - 1] + a[i] > a[i] ? f[i - 1] + a[i] : a[i]; // 动态转移方程        res = res > f[i] ? res : f[i]; // 更新最大值    }    printf("%d\n", res); // 输出子段的最大和    return 0;}

P1296 分形宇宙

C++

#include <iostream>#include <cmath>using namespace std;const int N = 4000;char g[N][N]; // 定义二维字符数组,存储分形图int n; // 定义分形图的度void dfs(int x, int y, int k) { // 定义递归函数    if (k == 1) { // 递归边界,一度分形就是一个点        g[x][y] = 'X';        return;    }    int len = pow(3, k - 2); // 每个子分形的长度    dfs(x, y, k - 1); // 左上角子分形    dfs(x, y + 2 * len, k - 1); // 右上角子分形    dfs(x + len, y + len, k - 1); // 中间子分形    dfs(x + 2 * len, y, k - 1); // 左下角子分形    dfs(x + 2 * len, y + 2 * len, k - 1); // 右下角子分形    for (int i = x; i < x + len; i++) { // 添加连线        g[i][y + len] = ' ';    }    for (int i = y; i < y + 2 * len; i++) { // 添加连线        g[x + len][i] = '-';    }}int main() {    while (cin >> n) {        int len = pow(3, n - 1); // 计算分形的长度        for (int i = 0; i < len; i++) { // 初始化分形图            for (int j = 0; j < len; j++) {                g[i][j] = ' ';            }        }        dfs(0, 0, n); // 生成分形图        for (int i = 0; i < len; i++) { // 输出分形图            for (int j = 0; j < len; j++) {                cout << g[i][j];            }            cout << endl;        }        cout << '-' << endl; // 分割线    }    return 0;}

C:

#include <stdio.h>#include <math.h>#define N 4000char g[N][N]; // 定义二维字符数组,存储分形图int n; // 定义分形图的度void dfs(int x, int y, int k) { // 定义递归函数    if (k == 1) { // 递归边界,一度分形就是一个点        g[x][y] = 'X';        return;    }    int len = pow(3, k - 2); // 每个子分形的长度    dfs(x, y, k - 1); // 左上角子分形    dfs(x, y + 2 * len, k - 1); // 右上角子分形    dfs(x + len, y + len, k - 1); // 中间子分形    dfs(x + 2 * len, y, k - 1); // 左下角子分形    dfs(x + 2 * len, y + 2 * len, k - 1); // 右下角子分形    for (int i = x; i < x + len; i++) { // 添加连线        g[i][y + len] = ' ';    }    for (int i = y; i < y + 2 * len; i++) { // 添加连线        g[x + len][i] = '-';    }}int main() {    while (scanf("%d", &n) != EOF) {        int len = pow(3, n - 1); // 计算分形的长度        for (int i = 0; i < len; i++) { // 初始化分形图            for (int j = 0; j < len; j++) {                g[i][j] = ' ';            }        }        dfs(0, 0, n); // 生成分形图        for (int i = 0; i < len; i++) { // 输出分形图            for (int j = 0; j < len; j++) {                printf("%c", g[i][j]);            }            printf("\n");        }        printf("-\n"); // 分割线    }    return 0;}

P1305 素数环

C++

#include <iostream>#include <vector>#include <cstring>using namespace std;const int MAXN = 20;int n;vector<int> path; // 存储当前的素数环bool used[MAXN]; // 记录数字是否使用过bool is_prime[50]; // 记录素数void dfs(int k) { // k表示当前要填的数字    if (k == n) { // 递归边界,当前素数环填满        if (is_prime[path[0] + path[n - 1]]) { // 判断首尾数字的和是否为素数            cout << path[0];            for (int i = 1; i < n; i++) {                cout << " " << path[i];            }            cout << endl;        }        return;    }    for (int i = 2; i <= n; i++) { // 枚举当前要填的数字        if (used[i]) continue; // 当前数字已经使用过了        if (!is_prime[i + path[k - 1]]) continue; // 当前数字和前一个数字的和不是素数        used[i] = true;        path.push_back(i);        dfs(k + 1);        path.pop_back();        used[i] = false;    }}int main() {    // 预处理素数表    memset(is_prime, true, sizeof(is_prime));    is_prime[0] = is_prime[1] = false;    for (int i = 2; i < 50; i++) {        if (is_prime[i]) {            for (int j = i * i; j < 50; j += i) {                is_prime[j] = false;            }        }    }    // 处理输入输出    int cnt = 0;    while (cin >> n) {        if (cnt > 0) cout << endl; // 多组数据之间的分隔符        cnt++;        cout << "Case " << cnt << ":" << endl;        path.clear(); // 清空存储当前素数环的vector        memset(used, false, sizeof(used));        used[1] = true; // 素数环从1开始        path.push_back(1);        dfs(1);    }    return 0;}

C:

#include <stdio.h>#include <stdbool.h>#include <string.h>#define MAXN 20int n;int path[MAXN]; // 存储当前的素数环bool used[MAXN]; // 记录数字是否使用过bool is_prime[50]; // 记录素数void dfs(int k) { // k表示当前要填的数字    if (k == n) { // 递归边界,当前素数环填满        if (is_prime[path[0] + path[n - 1]]) { // 判断首尾数字的和是否为素数            printf("%d", path[0]);            for (int i = 1; i < n; i++) {                printf(" %d", path[i]);            }            printf("\n");        }        return;    }    for (int i = 2; i <= n; i++) { // 枚举当前要填的数字        if (used[i]) continue; // 当前数字已经使用过了        if (!is_prime[i + path[k - 1]]) continue; // 当前数字和前一个数字的和不是素数        used[i] = true;        path[k] = i;        dfs(k + 1);        used[i] = false;    }}int main() {    // 预处理素数表    memset(is_prime, true, sizeof(is_prime));    is_prime[0] = is_prime[1] = false;    for (int i = 2; i < 50; i++) {        if (is_prime[i]) {            for (int j = i * i; j < 50; j += i) {                is_prime[j] = false;            }        }    }    // 处理输入输出    int cnt = 0;    while (scanf("%d", &n) != EOF) {        if (cnt > 0) printf("\n"); // 多组数据之间的分隔符        cnt++;        printf("Case %d:\n", cnt);        memset(used, false, sizeof(used));        used[1] = true; // 素数环从1开始        path[0] = 1;        dfs(1);    }    return 0;}

P1357 食物链(一)

C++:

#include <iostream>#include <vector>#include <cstring>using namespace std;const int MAXN = 1005;int n, m;vector<int> graph[MAXN];bool vis[MAXN];int ans = 0;void dfs(int u, int depth) {    ans = max(ans, depth);    for (int i = 0; i < graph[u].size(); i++) {        int v = graph[u][i];        if (!vis[v]) {            vis[v] = true;            dfs(v, depth+1);            vis[v] = false;        }    }}int main() {    while (cin >> n >> m) {        memset(vis, false, sizeof(vis));        ans = 0;        for (int i = 1; i <= n; i++) {            graph[i].clear();        }        for (int i = 0; i < m; i++) {            int u, v;            cin >> u >> v;            graph[u].push_back(v);        }        for (int i = 1; i <= n; i++) {            vis[i] = true;            dfs(i, 1);            vis[i] = false;        }        cout << ans << endl;    }    return 0;}

P1439 背包九讲(1):简单的0-1背包

C++:

#include <iostream>#include <cstring>using namespace std;const int MAX_N = 30;   // 物品最大数量const int MAX_V = 20000; // 箱子最大容量int n, V;   // n表示物品数量,V表示箱子容量int w[MAX_N], v[MAX_N]; // w表示每个物品的价值,v表示每个物品的体积int dp[MAX_N + 1][MAX_V + 1];    // dp数组表示在前i个物品中,容量为j的情况下,能获得的最大价值int main(){    cin >> V >> n;    for (int i = 0; i < n; ++i) {        cin >> v[i] >> w[i];    }    // 初始化第0行和第0列的值为0    memset(dp, 0, sizeof(dp));    // 计算dp数组    for (int i = 0; i < n; ++i) {        for (int j = 0; j <= V; ++j) {            if (j < v[i]) {                dp[i + 1][j] = dp[i][j];    // 放不下,继承上一行的值            } else {                dp[i + 1][j] = max(dp[i][j], dp[i][j - v[i]] + w[i]); // 取较大值            }        }    }    // 输出结果    cout << dp[n][V] << endl;    return 0;}

C:

#include <stdio.h>#include <string.h>#define MAX_N 30   // 物品最大数量#define MAX_V 20000 // 箱子最大容量int n, V;   // n表示物品数量,V表示箱子容量int w[MAX_N], v[MAX_N]; // w表示每个物品的价值,v表示每个物品的体积int dp[MAX_N + 1][MAX_V + 1];    // dp数组表示在前i个物品中,容量为j的情况下,能获得的最大价值int max(int a, int b){    return a > b ? a : b;}int main(){    scanf("%d%d", &V, &n);    for (int i = 0; i < n; ++i) {        scanf("%d%d", &v[i], &w[i]);    }    // 初始化第0行和第0列的值为0    memset(dp, 0, sizeof(dp));    // 计算dp数组    for (int i = 0; i < n; ++i) {        for (int j = 0; j <= V; ++j) {            if (j < v[i]) {                dp[i + 1][j] = dp[i][j];    // 放不下,继承上一行的值            } else {                dp[i + 1][j] = max(dp[i][j], dp[i][j - v[i]] + w[i]); // 取较大值            }        }    }    // 输出结果    printf("%d\n", dp[n][V]);    return 0;}

P1475 智力大冲浪

C++:

#include <iostream>#include <cstring>using namespace std;const int MAX_N = 30;   // 物品最大数量const int MAX_V = 20000; // 箱子最大容量int n, V;   // n表示物品数量,V表示箱子容量int w[MAX_N], v[MAX_N]; // w表示每个物品的价值,v表示每个物品的体积int dp[MAX_N + 1][MAX_V + 1];    // dp数组表示在前i个物品中,容量为j的情况下,能获得的最大价值int max(int a, int b){    return a > b ? a : b;}int main(){    // 输入数据    cin >> V >> n;    for (int i = 0; i < n; ++i) {        cin >> v[i] >> w[i];    }    // 初始化dp数组    memset(dp, 0, sizeof(dp));    // 计算dp数组    for (int i = 0; i < n; ++i) {        for (int j = 0; j <= V; ++j) {            if (j < v[i]) {                // 如果当前物品体积大于当前剩余容量,则不能放入箱子中,继承上一行的结果                dp[i + 1][j] = dp[i][j];            } else {                // 如果当前物品可以放入箱子中,则考虑将这个物品放入箱子中能带来多大的价值,取较大值                dp[i + 1][j] = max(dp[i][j], dp[i][j - v[i]] + w[i]);            }        }    }    // 输出结果    cout << dp[n][V] << endl;    return 0;}

C:

#include <stdio.h>#include <string.h>#define MAX_N 30   // 物品最大数量#define MAX_V 20000 // 箱子最大容量int n, V;   // n表示物品数量,V表示箱子容量int w[MAX_N], v[MAX_N]; // w表示每个物品的价值,v表示每个物品的体积int dp[MAX_N + 1][MAX_V + 1];    // dp数组表示在前i个物品中,容量为j的情况下,能获得的最大价值int max(int a, int b){    return a > b ? a : b;}int main(){    // 输入数据    scanf("%d%d", &V, &n);    for (int i = 0; i < n; ++i) {        scanf("%d%d", &v[i], &w[i]);    }    // 初始化dp数组    memset(dp, 0, sizeof(dp));    // 计算dp数组    for (int i = 0; i < n; ++i) {        for (int j = 0; j <= V; ++j) {            if (j < v[i]) {                // 如果当前物品体积大于当前剩余容量,则不能放入箱子中,继承上一行的结果                dp[i + 1][j] = dp[i][j];            } else {                // 如果当前物品可以放入箱子中,则考虑将这个物品放入箱子中能带来多大的价值,取较大值                dp[i + 1][j] = max(dp[i][j], dp[i][j - v[i]] + w[i]);            }        }    }    // 输出结果    printf("%d\n", dp[n][V]);    return 0;}

P1476 加工生产调度

C++:

#include <iostream>#include <cstring>#include <queue>#include <vector>using namespace std;const int MAX_N = 1000;int n;  // 产品的数量int time_a[MAX_N], time_b[MAX_N];  // time_a表示每个产品在A车间加工所需要的时间,time_b表示每个产品在B车间加工所需要的时间int in_degree[MAX_N];   // 记录每个产品的入度vector<int> edges[MAX_N];   // 采用邻接表存储图int main(){    while (cin >> n) {        // 输入数据        for (int i = 0; i < n; ++i) {            cin >> time_a[i];        }        for (int i = 0; i < n; ++i) {            cin >> time_b[i];        }        // 初始化        memset(in_degree, 0, sizeof(in_degree));        for (int i = 0; i < n; ++i) {            edges[i].clear();        }        // 建立A车间到B车间的依赖关系        for (int i = 0; i < n; ++i) {            for (int j = i + 1; j < n; ++j) {                if (time_a[i] + time_b[i] > time_a[j] + time_b[j]) {                    edges[j].push_back(i);                    ++in_degree[i];                } else {                    edges[i].push_back(j);                    ++in_degree[j];                }            }        }        // 拓扑排序        int time = 0;        queue<int> q;        for (int i = 0; i < n; ++i) {            if (in_degree[i] == 0) {                q.push(i);            }        }        while (!q.empty()) {            int u = q.front();            q.pop();            time = max(time, time_a[u]);    // 计算加工时间            for (int i = 0; i < edges[u].size(); ++i) {                int v = edges[u][i];                --in_degree[v];                if (in_degree[v] == 0) {                    q.push(v);                }            }        }        time += time_b[n - 1];  // 加上最后一个产品在B车间加工的时间        // 输出结果        cout << time << endl;    }    return 0;}

P1477 部分背包问题

C++:

#include <iostream>#include <algorithm>#include <cstring>using namespace std;const int MAX_N = 100;const int MAX_T = 1000;struct Item {    int weight; // 金币的重量    int value;  // 金币的价值    double unit_price;  // 金币的单位价值    bool operator < (const Item& other) const {        return unit_price > other.unit_price;    }};Item items[MAX_N];int n, T;   // n表示金币的数量,T表示背包的承重量int main(){    // 输入数据    cin >> n >> T;    for (int i = 0; i < n; ++i) {        cin >> items[i].weight >> items[i].value;        items[i].unit_price = (double)items[i].value / items[i].weight;    }    // 按照单位价值从大到小排序    sort(items, items + n);    // 计算最大价值    double ans = 0;    for (int i = 0; i < n; ++i) {        if (T >= items[i].weight) { // 如果可以将整个物品放入背包中            ans += items[i].value;            T -= items[i].weight;        } else {    // 否则将物品拆分            ans += T * items[i].unit_price;            break;        }    }    // 输出结果    printf("%.2lf\n", ans);    return 0;}

B1631 [Usaco2007 Feb]Cow Party

C++:

#include <iostream>#include <cstring>#include <algorithm>#include <queue>using namespace std;const int MAX_N = 1003;const int MAX_M = 100003;const int INF = 0x3f3f3f3f;struct Edge {    int v, w;   // v表示边的终点,w表示边的长度    int next;   // next表示下一个与起点相同的边的编号};Edge edges[MAX_M];  // 存储所有的边int head[MAX_N];    // head[i]表示起点为i的所有边中编号最小的那条边的编号int dist[MAX_N];    // dist[i]表示从终点到i的最短距离bool visited[MAX_N];    // visited[i]表示终点到i的最短路是否已经确定int n, m, x;    // n表示点的数量,m表示边的数量,x表示终点的编号void addEdge(int u, int v, int w, int id){    edges[id].v = v;    edges[id].w = w;    edges[id].next = head[u];    head[u] = id;}void dijkstra(){    memset(dist, INF, sizeof(dist));    memset(visited, false, sizeof(visited));    dist[x] = 0;    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;    pq.push(make_pair(dist[x], x));    while (!pq.empty()) {        int u = pq.top().second;        pq.pop();        if (visited[u]) continue;        visited[u] = true;        for (int i = head[u]; i != -1; i = edges[i].next) {            int v = edges[i].v;            int w = edges[i].w;            if (dist[v] > dist[u] + w) {                dist[v] = dist[u] + w;                pq.push(make_pair(dist[v], v));            }        }    }}int main(){    // 输入数据    cin >> n >> m >> x;    memset(head, -1, sizeof(head));    for (int i = 0; i < m; ++i) {        int u, v, w;        cin >> u >> v >> w;        addEdge(v, u, w, i);    }    // 计算最短路    dijkstra();    // 找到最大值    int ans = 0;    for (int i = 1; i <= n; ++i) {        if (dist[i] != INF) {            for (int j = head[i]; j != -1; j = edges[j].next) {                int v = edges[j].v;                int w = edges[j].w;                ans = max(ans, dist[i] + dist[v] + w);            }        }    }    // 输出结果    cout << ans << endl;    return 0;}

B3408 [Usaco2009 Oct]Heat Wave 热浪

C++:

#include <iostream>#include <vector>#include <queue>#include <cstring>using namespace std;const int N = 2510, M = 3 * 6200; // 根据题目要求设置节点数和边数的上限int h[N], e[M], w[M], ne[M], idx; // 邻接表存图,idx 表示当前边的编号int dist[N]; // 存储从起点到每个节点的最短距离bool st[N]; // 标记每个节点是否已经加入到 S 集合中int n, m, s, t;void add(int a, int b, int c) // 添加一条边 a -> b,边权为 c{    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;}int dijkstra() // 返回从起点到终点的最短距离{    memset(dist, 0x3f, sizeof dist); // 初始化为无穷大    dist[s] = 0;    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;    q.push({0, s});    while (q.size())    {        auto t = q.top();        q.pop();        int ver = t.second, distance = t.first;        if (st[ver]) continue;        st[ver] = true;        for (int i = h[ver]; i != -1; i = ne[i])        {            int j = e[i];            if (dist[j] > distance + w[i])            {                dist[j] = distance + w[i];                q.push({dist[j], j});            }        }    }    if (dist[t] == 0x3f3f3f3f) return -1;    return dist[t];}int main(){    memset(h, -1, sizeof h);    cin >> n >> m >> s >> t;    while (m -- )    {        int a, b, c;        cin >> a >> b >> c;        add(a, b, c);        add(b, a, c); // 无向图,所以要添加两条边    }    cout << dijkstra() << endl;    return 0;}

B3445 [Usaco2014 Feb] Roadblock

C++:

P1635 月饼

C++:

#include <iostream>#include <vector>#include <algorithm>using namespace std;struct MoonCake {    int t, b, h;    // t为进食时间,b为过期时间,h为快乐值};int main() {    int n, T;    cin >> n >> T;    vector<MoonCake> cakes(n);    for (int i = 0; i < n; i++) {        cin >> cakes[i].t >> cakes[i].b >> cakes[i].h;    }    // 将月饼按照过期时间从早到晚排序    sort(cakes.begin(), cakes.end(), [](const MoonCake& a, const MoonCake& b) {        return a.b < b.b;    });    // 动态规划,dp[i][j]表示考虑前i个月饼,限制时间为j时的最大快乐值    vector<vector<int>> dp(n + 1, vector<int>(T + 1));    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= T; j++) {            // 先不选第i个月饼            dp[i][j] = dp[i - 1][j];            // 判断能否选第i个月饼,即限制时间是否大于等于月饼的过期时间            if (j >= cakes[i - 1].b) {                // 选第i个月饼                dp[i][j] = max(dp[i][j], dp[i - 1][j - cakes[i - 1].t] + cakes[i - 1].h);            }        }    }    cout << dp[n][T] << endl;    return 0;}

P1648 炼丹术

C++:

#include <iostream>#include <vector>using namespace std;const int MOD = 998244353;int main() {    int n;    cin >> n;    vector<int> a(n);    for (int i = 0; i < n; i++) {        cin >> a[i];        a[i]--;    }    // 计算出所有S(A)等于A的药材集合的数量    vector<int> dp(n + 1);    dp[0] = 1;    for (int i = 1; i <= n; i++) {        // 计算f[i][j]        for (int j = i - 1; j >= 0; j--) {            dp[j + 1] = (dp[j] - dp[j + 1] + MOD) % MOD;        }        dp[0] = 1;        // 统计所有f[n][k]的值之和        int ans = 0;        for (int k = 1; k <= i; k++) {            ans = (ans + 1LL * dp[k] * (n - k + 1) % MOD) % MOD;        }        cout << ans << endl;        // 更新dp数组        for (int j = i; j >= 0; j--) {            if (j > 0) {                dp[j] = (dp[j] + dp[j - 1]) % MOD;            }        }    }    return 0;}

P1719 Let's play a game!

C++:

#include <iostream>#include <vector>using namespace std;// 返回一个整数的二进制表示中,1的个数int count_bits(int x) {    int res = 0;    while (x > 0) {        res += x & 1;        x >>= 1;    }    return res;}int main() {    int n, k;    cin >> n >> k;    vector<int> a(n);    for (int i = 0; i < n; i++) {        cin >> a[i];    }    // 计算所有元素为k的下标    vector<int> idx;    for (int i = 0; i < n; i++) {        if (a[i] == k) {            idx.push_back(i);        }    }    // 枚举所有可能的删除方案,求最小删除次数    int ans = n;    for (int b = 0; b <= 30; b++) {        int mask = (1 << b) - 1;        for (int i = 0; i < idx.size(); i++) {            // 如果i个数全部被删除,需要的操作次数            int cnt = count_bits((idx[i] >> b) ^ mask);            // 判断是否满足所有元素均为k            bool flag = true;            for (int j = 0; j < idx.size(); j++) {                if ((idx[i] >> b) != (idx[j] >> b)) {                    flag = false;                    break;                }            }            if (flag) {                ans = min(ans, cnt);            }        }    }    cout << ans << endl;    return 0;}

P1740 Ink on paper

C++:

#include <iostream>#include <vector>#include <queue>#include <cmath>using namespace std;const double INF = 1e20;// 计算两个点之间的距离double dist(double x1, double y1, double x2, double y2) {    return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));}int main() {    int T;    cin >> T;    while (T--) {        int n;        cin >> n;        // 读入所有的点        vector<double> x(n), y(n);        for (int i = 0; i < n; i++) {            cin >> x[i] >> y[i];        }        // 最短路径数组        vector<double> d(n, INF);        // 最小堆,存储待处理的点        priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;        // 初始点为第一个点,距离为0        d[0] = 0;        pq.push({0, 0});        while (!pq.empty()) {            // 取出当前距离最小的点            auto [dist, u] = pq.top();            pq.pop();            // 如果这个点已经处理过了,直接跳过            if (dist > d[u]) {                continue;            }            // 处理所有与当前点相邻的点            for (int v = 0; v < n; v++) {                if (v == u) {                    continue;                }                double w = dist(x[u], y[u], x[v], y[v]) - 1.0;                if (w < 0) {                    w = 0;                }                // 如果能够缩短到v点的距离,则更新                if (d[v] > d[u] + w) {                    d[v] = d[u] + w;                    pq.push({d[v], v});                }            }        }        // 输出答案的平方        printf("%.0f\n", d[n-1] * d[n-1]);    }    return 0;}

P1743 Audiophobia

C++:

#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;const int N = 110;const int M = 1010;struct Edge {    int next; // 下一条边的编号    int to; // 目标节点编号    int w; // 权值} edge[M << 1];int head[N], tot;int n, m, q;void add(int u, int v, int w) { // 添加一条边    edge[++tot].to = v;    edge[tot].w = w;    edge[tot].next = head[u];    head[u] = tot;}struct Node {    int dis; // 距离    int id; // 节点编号    bool operator < (const Node &W) const {        return dis > W.dis;    }};bool vis[N];int dis[N];int dijkstra(int s, int t) { // s为起点,t为终点    priority_queue<Node> q; // 小根堆    memset(vis, false, sizeof(vis));    memset(dis, 0x3f, sizeof(dis));    dis[s] = 0; // 起点距离为0    q.push({0, s}); // 把起点加入队列    while (!q.empty()) {        Node now = q.top(); q.pop();        int u = now.id;        if (vis[u]) continue; // 已经访问过了        vis[u] = true; // 标记为已经访问        for (int i = head[u]; i; i = edge[i].next) {            int v = edge[i].to;            if (dis[v] > max(dis[u], edge[i].w)) { // 更新距离                dis[v] = max(dis[u], edge[i].w);                q.push({dis[v], v}); // 把新节点加入队列            }        }    }    if (dis[t] == 0x3f3f3f3f) return -1; // 没有路径    else return dis[t]; // 返回最短距离}int main() {    int T = 0; // 样例编号    while (scanf("%d%d%d", &n, &m, &q) != EOF) {        memset(head, 0, sizeof(head));        tot = 0;        for (int i = 1; i <= m; i++) {            int u, v, w;            scanf("%d%d%d", &u, &v, &w);            add(u, v, w);            add(v, u, w); // 无向图,要加两次        }        printf("Case #%d\n", ++T); // 样例编号加1        while (q--) {            int s, t;            scanf("%d%d", &s, &t);            int res = dijkstra(s, t);            if (res == -1) puts("no path"); // 没有路径            else printf("%d\n", res);        }    }    return 0;}

P1747 单调不降序列中与x最接近元素

C++:

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int N = 100010;int a[N];int main() {    int n;    scanf("%d", &n);    for (int i = 0; i < n; i++) scanf("%d", &a[i]);    int m;    scanf("%d", &m);    while (m--) {        int x;        scanf("%d", &x);        int l = 0, r = n - 1;        while (l < r) {            int mid = (l + r) >> 1;            if (a[mid] >= x) r = mid; // 右半部分有可能更小            else l = mid + 1; // 左半部分肯定不符合要求        }        if (l == 0) printf("%d\n", a[0]); // 特判        else if (l == n - 1) printf("%d\n", a[n - 1]); // 特判        else {            if (a[l] - x <= x - a[l - 1]) printf("%d\n", a[l]); // 找到了更小的元素            else printf("%d\n", a[l - 1]); // 找到了更小的元素        }    }    return 0;}

P1748 a+b+c+d==0

C++:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <unordered_map>using namespace std;const int N = 2010;int a[N], b[N], c[N], d[N];int n;int main() {    int T;    scanf("%d", &T);    while (T--) {        scanf("%d", &n);        for (int i = 0; i < n; i++) scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]);        unordered_map<int, int> mp;        for (int i = 0; i < n; i++) { // 枚举a和b的组合            for (int j = 0; j < n; j++) {                mp[a[i] + b[j]]++;            }        }        int res = 0;        for (int i = 0; i < n; i++) { // 枚举c和d的组合            for (int j = 0; j < n; j++) {                int sum = c[i] + d[j];                if (mp.count(-sum)) res += mp[-sum]; // 找到了和为-sum的组合            }        }        printf("%d\n", res);    }    return 0;}

P1750 求逆序对

C++:

#include <iostream>#include <cstdio>#include <cstring>using namespace std;typedef long long LL; // 要开long longconst int N = 500010;int a[N], tmp[N];LL res;void merge_sort(int l, int r) {    if (l >= r) return;    int mid = (l + r) >> 1;    merge_sort(l, mid);    merge_sort(mid + 1, r);    int i = l, j = mid + 1, k = 0;    while (i <= mid && j <= r) { // 统计逆序对的个数        if (a[i] <= a[j]) tmp[k++] = a[i++];        else {            tmp[k++] = a[j++];            res += mid - i + 1; // 统计个数        }    }    while (i <= mid) tmp[k++] = a[i++];    while (j <= r) tmp[k++] = a[j++];    for (int i = l, j = 0; i <= r; i++, j++) a[i] = tmp[j];}int main() {    int n;    scanf("%d", &n);    for (int i = 0; i < n; i++) scanf("%d", &a[i]);    merge_sort(0, n - 1);    printf("%lld\n", res);    return 0;}

P1763 friendly group

C++:

#include <iostream>#include <cstdio>#include <cstring>#include <vector>using namespace std;const int N = 300010;int h[N], e[N], ne[N], idx; // 邻接表int color[N], cnt[2], f[N]; // cnt[0]和cnt[1]是染色后两种颜色的点数,f[i]表示以点i为根的子树中选或不选i的最大权值和vector<int> v; // 存放当前独立集中的点void add(int a, int b) {    e[idx] = b, ne[idx] = h[a], h[a] = idx++;}bool dfs(int u, int c) { // 二分图染色    color[u] = c;    cnt[c]++;    for (int i = h[u]; i != -1; i = ne[i]) {        int j = e[i];        if (color[j] == -1) {            if (!dfs(j, !c)) return false;        }        else if (color[j] == c) return false;    }    return true;}void dfs2(int u, int father) { // 计算f数组    int t = v.size();    for (int i = h[u]; i != -1; i = ne[i]) {        int j = e[i];        if (j == father) continue;        dfs2(j, u);    }    if (!t) { // u是根节点,若选它,则其所有子节点都不能选        f[u] = cnt[1];        for (int i = h[u]; i != -1; i = ne[i]) {            int j = e[i];            f[u] = max(f[u], cnt[1] - f[j]);        }    }    else {        v.push_back(u); // 将u加入当前独立集        f[u] = cnt[color[u] == 0]; // 以u为根节点的子树中选或不选u的最大权值和        for (int i = h[u]; i != -1; i = ne[i]) {            int j = e[i];            if (j == father) continue;            f[u] += f[j];        }        v.pop_back(); // 将u移出当前独立集        f[u] = max(f[u], f[father]); // u不选,其子节点都可选    }}int main() {    int T;    scanf("%d", &T);    for (int C = 1; C <= T; C++) {        int n, m;        scanf("%d%d", &n, &m);        memset(h, -1, sizeof h);        idx = 0;        for (int i = 0; i < m; i++) {            int a, b;            scanf("%d%d", &a, &b);            add(a, b);            add(b, a);        }        memset(color, -1, sizeof color);        bool flag = true;        int ans = 0;        for (int i = 1; i <= n; i++) {            if (color[i] == -1) {                cnt[0]

P1779 小胡同学的跳板

C++:

#include <iostream>#include <vector>#include <algorithm>using namespace std;int main() {    int n, m;    cin >> n >> m;    vector<pair<int, int>> boards(n); // 记录每个跳板的位置和能够发射的距离    for (int i = 0; i < n; i++) {        cin >> boards[i].first >> boards[i].second;    }    sort(boards.begin(), boards.end()); // 按照跳板的位置从小到大排序    int farthest = 0; // 记录当前位置下能够到达的最远距离    int idx = 0; // 记录当前使用的跳板的下标    int steps = 0; // 记录走的总步数    while (farthest < m) {        int max_distance = farthest; // 记录能够到达的最远距离        while (idx < n && boards[idx].first <= farthest) {            // 遍历当前能够到达的跳板,找到其中能够发射最远距离的跳板            max_distance = max(max_distance, boards[idx].first + boards[idx].second);            idx++;        }        if (max_distance == farthest) {            // 无法继续前进,退出循环            break;        }        steps++;        farthest = max_distance;    }    if (farthest < m) {        // 无法到达炸鸡店,输出-1        cout << "-1" << endl;    } else {        cout << steps << endl;    }    return 0;}

P1790 小胡同学的连通图

C++:

#include <iostream>#include <vector>#include <queue>using namespace std;int main() {    int n, m;    cin >> n >> m;    // 使用邻接表表示图    vector<vector<int>> graph(n + 1);    for (int i = 0; i < m; i++) {        int u, v;        cin >> u >> v;        graph[u].push_back(v);        graph[v].push_back(u);    }    vector<bool> visited(n + 1, false); // 标记节点是否被访问过    queue<int> q; // 队列用于BFS遍历    q.push(1);    visited[1] = true;    while (!q.empty()) {        int u = q.front();        q.pop();        for (int v : graph[u]) {            if (!visited[v]) {                q.push(v);                visited[v] = true;            }        }    }    for (int i = 1; i <= n; i++) {        if (!visited[i]) {            // 存在未被访问到的节点,说明不是连通图            cout << "No" << endl;            return 0;        }    }    cout << "Yes" << endl;    return 0;}

P1793 求解迷宫问题

C++:

#include <iostream>#include <vector>using namespace std;const int N = 8; // 迷宫的大小vector<vector<char>> maze(N, vector<char>(N)); // 保存迷宫的二维数组vector<vector<int>> path(N, vector<int>(N, 0)); // 保存路径的二维数组,0表示未访问过,1表示已访问过bool found = false; // 是否已经找到一条路径void dfs(int x, int y) {    if (x < 0 || x >= N || y < 0 || y >= N) {        // 当前位置越界        return;    }    if (maze[x][y] == 'X' || path[x][y] == 1) {        // 当前位置是障碍,或者已经被访问过        return;    }    if (x == N - 1 && y == N - 1) {        // 已经到达出口        found = true;        path[x][y] = 1;        return;    }    // 标记当前位置已经被访问    path[x][y] = 1;    dfs(x - 1, y); // 左    if (found) {        // 已经找到一条路径,返回        return;    }    dfs(x, y + 1); // 上    if (found) {        // 已经找到一条路径,返回        return;    }    dfs(x + 1, y); // 右    if (found) {        // 已经找到一条路径,返回        return;    }    dfs(x, y - 1); // 下    if (found) {        // 已经找到一条路径,返回        return;    }    // 回溯,将当前位置标记为未访问    path[x][y] = 0;}int main() {    // 读入迷宫    for (int i = 0; i < N; i++) {        for (int j = 0; j < N; j++) {            cin >> maze[i][j];        }    }    dfs(0, 0); // 从入口开始DFS遍历    // 输出路径    for (int i = 0; i < N; i++) {        for (int j = 0; j < N; j++) {            if (path[i][j] == 1) {                cout << "O";            } else {                cout << " ";            }        }        cout << endl;    }    return 0;}

P1794 求解好多鱼问题

C++:

#include <iostream>#include <vector>#include <cmath>using namespace std;int main() {    int minSize, maxSize, n;    cin >> minSize >> maxSize >> n;    vector<int> fishSize(n);    for (int i = 0; i < n; i++) {        cin >> fishSize[i];    }    int count = 0;    for (int i = minSize; i <= maxSize; i++) {        bool safe = true;        for (int j = 0; j < n; j++) {            if ((i >= fishSize[j] * 2 && i <= fishSize[j] * 100) ||                (fishSize[j] >= i * 2 && fishSize[j] <= i * 100)) {                // i能吃掉fishSize[j],或者fishSize[j]能吃掉i,i不安全                safe = false;                break;            }        }        if (safe) {            count++;        }    }    cout << count << endl;    return 0;}

P1795 求解图的 m 着色问题

C++:

#include <iostream>#include <vector>using namespace std;int n, k, m;vector<vector<int>> graph;  // 无向连通图vector<int> color;          // 各顶点的颜色int count = 0;              // 符合要求的着色方案数// 检查某个顶点的着色是否合法bool check(int v, int c) {    for (int i = 0; i < graph[v].size(); i++) {        int neighbor = graph[v][i];        if (color[neighbor] == c) {            return false;        }    }    return true;}// 递归枚举所有着色方案void dfs(int v) {    if (v == n) {        // 所有顶点都已着色,该方案符合要求        count++;        return;    }    // 尝试所有可能的颜色    for (int c = 1; c <= m; c++) {        if (check(v, c)) {            // 该颜色能用于该顶点,继续递归下一个顶点            color[v] = c;            dfs(v + 1);            color[v] = 0;  // 回溯        }    }}int main() {    cin >> n >> k >> m;    // 初始化图    graph.resize(n);    for (int i = 0; i < k; i++) {        int u, v;        cin >> u >> v;        u--;        v--;        graph[u].push_back(v);        graph[v].push_back(u);    }    // 初始化顶点颜色    color.resize(n);    // 从第一个顶点开始递归枚举所有着色方案    dfs(0);    cout << count << endl;    return 0;}

P1801 二叉排序树

C++:

#include <iostream>using namespace std;// 二叉树节点struct TreeNode {    int val;    TreeNode* left;    TreeNode* right;    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}};// 插入节点void insert(TreeNode* root, int val) {    if (root->val == val) return;  // 值已存在,无需插入    if (val < root->val) {        if (root->left == nullptr) {            root->left = new TreeNode(val);        } else {            insert(root->left, val);        }    } else {        if (root->right == nullptr) {            root->right = new TreeNode(val);        } else {            insert(root->right, val);        }    }}// 查询节点int search(TreeNode* root, int val, string& path) {    if (root == nullptr) return 0;  // 值不存在    if (val == root->val) return 1;  // 值存在    if (val < root->val) {        path += "<-";        return search(root->left, val, path) + 1;  // 继续在左子树查找    } else {        path += "->";        return search(root->right, val, path) + 1;  // 继续在右子树查找    }}int main() {    int n;    cin >> n;    TreeNode* root = nullptr;    for (int i = 0; i < n; i++) {        int opt, x;        cin >> opt >> x;        string path = "";        if (opt == 1) {            if (root == nullptr) {                root = new TreeNode(x);            } else {                insert(root, x);            }        } else {            int count = search(root, x, path) - 1;            cout << path << endl << count << endl;        }    }    return 0;}

P1809 wzy的跑步

C++:

#include <iostream>#include <vector>#include <algorithm>using namespace std;int main() {    int n, m, k;    cin >> n >> m >> k;    vector<int> puddles(m);    for (int i = 0; i < m; i++) {        cin >> puddles[i];    }    sort(puddles.begin(), puddles.end());  // 按照位置排序    int pos = 1, ans = 0;    while (pos < n) {        int nextPos = pos + k;        while (nextPos >= pos) {  // 在范围 [pos+1, pos+k] 内找到最后一个没有水坑的位置            auto it = lower_bound(puddles.begin(), puddles.end(), nextPos);            if (it == puddles.begin()) {                break;            }            it--;            if (*it < pos) {                break;            }            nextPos = *it + k;        }        if (nextPos == pos) {  // 无法前进            cout << "-1" << endl;            return 0;        }        ans += 1;        pos = nextPos;    }    cout << ans << endl;    return 0;}

P1825 东方香霖堂

C++:

#include <iostream>#include <algorithm>using namespace std;int main() {    int n, k;    cin >> n >> k;    int a[n];    for (int i = 0; i < n; i++) {        cin >> a[i];    }    sort(a, a + n);    int cnt = 0;    for (int i = 0; i < n; i++) {        if (a[i] <= k) {            cnt += 1;            k -= a[i];        } else {            break;        }    }    cout << cnt << endl;    return 0;}

P1826 荷取的基站布局

C++:

#include <iostream>#include <cstring>using namespace std;const int N = 15, MOD = 1e9 + 7;int n;bool placed[N][N];  // 标记第 i 行第 j 列是否已放置基站int ans = 0;void dfs(int x, int y, int k) {    if (y == n) {  // 换行        y = 0;        x += 1;    }    if (x == n) {  // 达到最后一个方格        if (k == n) {  // 找到一个合法布局方案            ans = (ans + 1) % MOD;        }        return;    }    bool canPlace = true;  // 判断当前方格能否放置基站    if (placed[x][y]) {  // 当前方格已经放置了基站        canPlace = false;    }    if (x > 0 && placed[x - 1][y]) {  // 上面的方格已经放置了基站        canPlace = false;    }    if (y > 0 && placed[x][y - 1]) {  // 左边的方格已经放置了基站        canPlace = false;    }    if (canPlace) {  // 可以放置基站        placed[x][y] = true;        dfs(x, y + 1, k + 1);        placed[x][y] = false;    }    dfs(x, y + 1, k);  // 不放置基站}int main() {    cin >> n;    dfs(0, 0, 0);    cout << ans << endl;    return 0;}

P1837 切出最好吃的蛋糕

C++:

#include <iostream>#include <cstring>using namespace std;const int N = 110;int n;int s[N][N];  // 二维前缀和数组int main() {    cin >> n;    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= n; j++) {            int x;            cin >> x;            s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + x;        }    }    int ans = -1e9;    for (int i = 1; i <= n; i++) {  // 枚举矩形左上角的位置        for (int j = 1; j <= n; j++) {            for (int k = i; k <= n; k++) {  // 枚举矩形右下角的位置                for (int l = j; l <= n; l++) {                    int sum = s[k][l] - s[k][j - 1] - s[i - 1][l] + s[i - 1][j - 1];  // 子矩形的和                    ans = max(ans, sum);  // 更新最大值                }            }        }    }    cout << ans << endl;    return 0;}

P1849 乌龟棋

C++:

#include <iostream>#include <vector>#include <algorithm>#include <unordered_set>using namespace std;int main(){    int n, m;    cin >> n >> m;    // 读入格子的分数    vector<int> scores(n);    for (int i = 0; i < n; ++i) {        cin >> scores[i];    }    // 读入卡片    vector<int> cards(m);    for (int i = 0; i < m; ++i) {        cin >> cards[i];    }    // 将卡片按数字从大到小排序    sort(cards.rbegin(), cards.rend());    // 已使用的卡片    unordered_set<int> used_cards;    // 可用的卡片    vector<int> available_cards;    // 初始化可用的卡片列表    for (int i = 0; i < m; ++i) {        available_cards.push_back(cards[i]);    }    // 从起点开始    int position = 0;    int total_score = scores[0];    // 当还没到达终点时    while (position < n - 1) {        // 找到可以使用的最大卡片        int max_card = -1;        for (int i = 0; i < available_cards.size(); ++i) {            if (used_cards.count(available_cards[i]) == 0) {                max_card = available_cards[i];                break;            }        }        // 使用最大卡片        used_cards.insert(max_card);        available_cards.erase(find(available_cards.begin(), available_cards.end(), max_card));        position += max_card;        total_score += scores[position];    }    cout << total_score << endl;    return 0;}

P1851 成熟的数列

C++:

#include <iostream>#include <unordered_map>#include <vector>using namespace std;int main(){    int x, y, z;    cin >> x >> y >> z;    // 计算数列    vector<int> sequence(z + 1);    sequence[0] = x;    sequence[1] = y;    unordered_map<int, int> seen;    seen[x] = 0;    seen[y] = 1;    int cycle_length = -1;    int cycle_start = -1;    for (int i = 2; i <= z; ++i) {        int a = sequence[i - 2];        int b = sequence[i - 1];        int c = a + sequence[(i / 2) + (i / 4)];        sequence[i] = c;        if (seen.count(c) != 0) {            cycle_length = i - seen[c];            cycle_start = seen[c];            break;        }        seen[c] = i;    }    // 处理查询    int n;    cin >> n;    int max_seen = -1;    unordered_map<int, int> recent;    for (int i = 0; i < n; ++i) {        int s;        cin >> s;        // 如果数列已经超过了查询数,查询数不在数列中        if (z >= s) {            if (seen.count(s) != 0) {                cout << seen[s] << endl;                continue;            }            if (cycle_length != -1 && s > sequence[cycle_start + cycle_length - 1]) {                cout << -1 << endl;                continue;            }        }        // 如果查询数在数列之外,计算数列的一部分        int start = max(max_seen, 0);        int end = min(s, z);        for (int j = start; j <= end; ++j) {            int a = sequence[j];            recent[a] = j;        }        max_seen = max(max_seen, end);        // 检查查询数是否在计算出的数列中        if (recent.count(s) != 0) {            cout << recent[s] << endl;        } else {            cout << -1 << endl;        }    }    return 0;}

P1852 舰长的礼物

C++:

#include <iostream>#include <vector>#include <algorithm>#include <numeric>using namespace std;const double EPS = 1e-8;int main(){    int n, k;    cin >> n >> k;    // 读入护心毛长度并求出平均值    vector<double> L(n);    double sum_L = 0;    for (int i = 0; i < n; ++i) {        cin >> L[i];        sum_L += L[i];    }    double avg = sum_L / k;    // 二分查找最大长度    double left = 0, right = avg;    double ans = -1;    while (right - left >= EPS) {        double mid = (left + right) / 2;        int cnt = accumulate(L.begin(), L.end(), 0, [&](int s, double l) { return s + static_cast<int>(l / mid); });        if (cnt >= k) {            ans = mid;            left = mid;        } else {            right = mid;        }    }    // 输出答案    if (ans != -1) {        printf("%.2f\n", ans);    } else {        cout << 0 << endl;    }    return 0;}

P1853 守望者的逃离

C++:

#include <iostream>#include <cmath>using namespace std;int main(){    int n, s, m, t;    cin >> n >> s >> m >> t;    // 若无法直接到达终点则先回到起点    if (n * 60 + s > 17 * t) {        n = 0;        s = 0;    }    int time = 0;    while (time < t) {        // 1. 尽量使用闪现        if (m >= 10 && s + 60 <= n * 60 + s && s + 60 <= 17 * t) {            s += 60;            m -= 10;        } else {            // 2. 如果无法使用闪现且距离终点超过当前时间能走的最远距离,则加速跑步            int max_dist = min(17 * (t - time), n * 60 + s + 17 * (t - time));            if (s + 1 < max_dist) {                s += 1;            }            // 3. 否则只能原地休息            else if (m + 4 <= 1000) {                m += 4;            }        }        // 更新时间        ++time;    }    // 输出结果    if (n * 60 + s >= 17 * t) {        cout << "Yes" << endl << time << endl;    } else {        cout << "No" << endl << n * 60 + s << endl;    }    return 0;}

P1855 接水问题

C++:

#include<bits/stdc++.h>using namespace std;const int MAXN=1e4+5;int n,m,ans=0;int cnt[MAXN];//每个同学还需要接水的量queue<int> q[MAXN];//队列模拟每个龙头接水情况int main(){    cin>>n>>m;    for(int i=1;i<=n;++i)    {        int w;        cin>>w;        cnt[i]=w;        q[i%m].push(i);    }    while(1)    {        bool flag=1;//标记是否全部同学都接完水了        for(int i=0;i<m;++i)//遍历每个龙头        {            if(q[i].empty()) continue;//如果该龙头上没有同学了            int cur=q[i].front();            flag=0;            --cnt[cur];            q[i].pop();            if(cnt[cur]==0)//如果该同学接完水了            {                if(q[(i+1)%m].empty())//下一个龙头空着,直接接上                    q[(i+1)%m].push(cur);                else//否则,入队等待                {                    q[(i+2)%m].push(cur);                    i++;                }            }        }        if(flag) break;//如果全部同学都接完水了,退出循环        ++ans;//每一秒都要加1    }    cout<<ans<<endl;    return 0;}

P1857 孤独摇滚

C++:波门

P1859 单词接龙

C++:

#include<bits/stdc++.h>using namespace std;int n;string s[25];char c;bool vis[25];int dfs(int u,string str)//深搜{    int res=str.size();    for(int i=1;i<=n;++i)    {        if(vis[i]) continue;//i已经被访问过了,跳过        vis[i]=1;//标记i为已访问        for(int j=1;j<s[i].size();++j)//枚举i的所有后缀        {            string suffix=s[i].substr(j);            if(suffix==str)//如果u和i可以拼接在一起            {                res=max(res,dfs(i,s[i])+str.size());//更新答案                break;            }        }        vis[i]=0;//回溯    }    return res;}int main(){    cin>>n;    for(int i=1;i<=n;++i) cin>>s[i];    cin>>c;    int ans=0;    for(int i=1;i<=n;++i)    {        if(s[i][0]==c)//如果s[i]以c开头        {            vis[i]=1;//标记i为已访问            ans=max(ans,dfs(i,s[i]));//更新答案            vis[i]=0;//回溯        }    }    cout<<ans<<endl;    return 0;}

点击全文阅读


本文链接:http://zhangshiyu.com/post/59201.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1