数据结构Pta训练题-编程2(1)

简介: 数据结构Pta训练题-编程

万字长文,整理不易。点赞加评论期末高分过!


感谢你这么帅(漂亮)还支持我


7-8 最短工期


一个项目由若干个任务组成,任务之间有先后依赖顺序。项目经理需要设置一系列里程碑,在每个里程碑节点处检查任务的完成情况,并启动后续的任务。现给定一个项目中各个任务之间的关系,请你计算出这个项目的最早完工时间。


输入格式:

首先第一行给出两个正整数:项目里程碑的数量 N(≤100)和任务总数 M。这里的里程碑从 0 到 N−1 编号。随后 M 行,每行给出一项任务的描述,格式为“任务起始里程碑 任务结束里程碑 工作时长”,三个数字均为非负整数,以空格分隔。


输出格式:

如果整个项目的安排是合理可行的,在一行中输出最早完工时间;否则输出"Impossible"。


输入样例 1:


9 12
0 1 6
0 2 4
0 3 5
1 4 1
2 4 1
3 5 2
5 4 0
4 6 9
4 7 7
5 7 4
6 8 2
7 8 4

输出样例 1:


18



输入样例 2:


4 5
0 1 1
0 2 2
2 1 3
1 3 4
3 2 5


解析


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int n, m, ans;
int mp[100][100];
int l[100], q[100], t[100];
int main() {
    int a, b, c, head = 0, tail = 0;
    scanf("%d%d", &n, &m);
    memset(mp, -1, sizeof(mp));
    for (int i = 0; i < m; i++) {
        scanf("%d%d%d", &a, &b, &c);
        mp[a][b] = c;
        l[b]++;
    }
    for (int i = 0; i < n; i++) {
        if (!l[i]) {
            q[tail++] = i;
        }
    }
    while (head < tail) {
        int temp = q[head++];
        if (t[temp] > ans) ans = t[temp];
        for (int i = 0; i < n; i++) {
            if (mp[temp][i] != -1) {
                l[i]--;
                if (!l[i]) q[tail++] = i;
                if (t[i] < t[temp] + mp[temp][i]) {
                    t[i] = t[temp] + mp[temp][i];
                }
            }
        }
    }
    if (tail < n) printf("Impossible");
    else printf("%d", ans);
}



7-9 哈利·波特的考试


哈利·波特要考试了,他需要你的帮助。这门课学的是用魔咒将一种动物变成另一种动物的本事。例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等。反方向变化的魔咒就是简单地将原来的魔咒倒过来念,例如ahah可以将老鼠变成猫。另外,如果想把猫变成鱼,可以通过念一个直接魔咒lalala,也可以将猫变老鼠、老鼠变鱼的魔咒连起来念:hahahehe。


现在哈利·波特的手里有一本教材,里面列出了所有的变形魔咒和能变的动物。老师允许他自己带一只动物去考场,要考察他把这只动物变成任意一只指定动物的本事。于是他来问你:带什么动物去可以让最难变的那种动物(即该动物变为哈利·波特自己带去的动物所需要的魔咒最长)需要的魔咒最短?例如:如果只有猫、鼠、鱼,则显然哈利·波特应该带鼠去,因为鼠变成另外两种动物都只需要念4个字符;而如果带猫去,则至少需要念6个字符才能把猫变成鱼;同理,带鱼去也不是最好的选择。


输入格式:

输入说明:输入第1行给出两个正整数N (≤100)和M,其中N是考试涉及的动物总数,M是用于直接变形的魔咒条数。为简单起见,我们将动物按1~N编号。随后M行,每行给出了3个正整数,分别是两种动物的编号、以及它们之间变形需要的魔咒的长度(≤100),数字之间用空格分隔。


输出格式:

输出哈利·波特应该带去考场的动物的编号、以及最长的变形魔咒的长度,中间以空格分隔。如果只带1只动物是不可能完成所有变形要求的,则输出0。如果有若干只动物都可以备选,则输出编号最小的那只。


输入样例:


6 11
3 4 70
1 2 1
5 4 50
2 6 50
5 6 60
1 3 70
4 6 60
3 6 80
5 1 100
2 4 60
5 2 80


输出样例:


4 70


解析


/**
 * 7-9 哈利·波特的考试
 *  最短路径     迪杰斯特拉算法
 */
#include<stdio.h>
#include<string.h>
#define maxInt 2147483647
typedef struct {
    int arcs[102][102];
    int vexnum, arcnum;
} MGraph;
int final[102];//final[w]=1表示求得顶点v0至vw的最短路径 
int D[102];  //记录v0到vi的当前最短路径长度
int P[102]; //记录v0到vi的当前最短路径vi的前驱
int i, u, j, m, v, min, w, k, a, b, c, min1 = 999999, max = -991111, p = 0;
void Dijkstra(MGraph G, int v0) {
    for (v = 0; v < G.vexnum; v++)    //初始化数据
    {
        final[v] = 0;            //全部顶点初始化为未知最短路径状态
        D[v] = G.arcs[v0][v];// 将与v0点有连线的顶点加上权值
        P[v] = -1;                //初始化路径数组P为-1
    }
    D[v0] = 0;  //v0至v0路径为0
    final[v0] = 1;    // v0至v0不需要求路径
    // 开始主循环,每次求得v0到某个v顶点的最短路径
    for (v = 1; v < G.vexnum; v++) {
        min = maxInt;    // 当前所知离v0顶点的最近距离
        for (w = 0; w < G.vexnum; w++) // 寻找离v0最近的顶点
        {
            if (!final[w] && D[w] < min) {
                k = w;
                min = D[w];    // w顶点离v0顶点更近
            }
        }
        final[k] = 1;    // 将目前找到的最近的顶点置为1
        for (w = 0; w < G.vexnum; w++) // 修正当前最短路径及距离
        {
            // 如果经过v顶点的路径比现在这条路径的长度短的话
            if (!final[w] && (min + G.arcs[k][w] < D[w])) { // 说明找到了更短的路径,修改D[w]和P[w]
                D[w] = min + G.arcs[k][w];  // 修改当前路径长度
                P[w] = k;
            }
        }
    }
}
int main() {
    MGraph G;
    memset(final, 0, sizeof(final));
    memset(D, 0x3f3f3f3f, sizeof(D));
    memset(G.arcs, 0x3f3f3f3f, sizeof(G.arcs));   //邻接矩阵一定要初始化
    scanf("%d %d", &G.vexnum, &m);
    for (i = 0; i < m; i++) {
        scanf("%d %d %d", &a, &b, &c);
        G.arcs[a - 1][b - 1] = c;
        G.arcs[b - 1][a - 1] = c;
    }
    for (u = 0; u < G.vexnum; u++) {
        max = -9999999;
        Dijkstra(G, u);
        for (j = 0; j < G.vexnum; j++) {
            if (D[j] > max)
                max = D[j];
        }
        if (max < min1) {
            min1 = max;
            p = u + 1;
        }
    }
    if (p == 0)
        printf("0");
    else
        printf("%d %d\n", p, min1);
    return 0;
}



7-10 旅游规划


有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。


输入格式:

输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。


输出格式:

在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。


输入样例:


4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20


输出样例:.


3 40


解析


#include <stdio.h>
#include <stdbool.h>
#define MAX_SIZE 500
#define INF 1000000
typedef struct {
    int city;
    int length;
    int fee;
} Road;
int dijkstra(Road graph[MAX_SIZE][MAX_SIZE], int N, int S, int D, int *path) {
    bool visited[MAX_SIZE] = {false};
    int distances[MAX_SIZE];
    int fees[MAX_SIZE];
    for (int i = 0; i < N; i++) {
        distances[i] = INF;
        fees[i] = INF;
        path[i] = -1;
    }
    distances[S] = 0;
    fees[S] = 0;
    for (int count = 0; count < N - 1; count++) {
        int minDist = INF;
        int minCity = -1;
        // 找到当前距离最小的城市
        for (int i = 0; i < N; i++) {
            if (!visited[i] && distances[i] < minDist) {
                minDist = distances[i];
                minCity = i;
            }
        }
        visited[minCity] = true;
        // 更新相邻城市的距离和费用
        for (int i = 0; i < N; i++) {
            if (!visited[i] && graph[minCity][i].city != -1) {
                int newDist = distances[minCity] + graph[minCity][i].length;
                int newFee = fees[minCity] + graph[minCity][i].fee;
                if (newDist < distances[i] || (newDist == distances[i] && newFee < fees[i])) {
                    distances[i] = newDist;
                    fees[i] = newFee;
                    path[i] = minCity;
                }
            }
        }
    }
    return distances[D];
}
int main() {
    int N, M, S, D;
    scanf("%d %d %d %d", &N, &M, &S, &D);
    Road graph[MAX_SIZE][MAX_SIZE];
    for (int i = 0; i < MAX_SIZE; i++) {
        for (int j = 0; j < MAX_SIZE; j++) {
            graph[i][j].city = -1;
            graph[i][j].length = -1;
            graph[i][j].fee = -1;
        }
    }
    for (int i = 0; i < M; i++) {
        int city1, city2, length, fee;
        scanf("%d %d %d %d", &city1, &city2, &length, &fee);
        graph[city1][city2].city = city2;
        graph[city1][city2].length = length;
        graph[city1][city2].fee = fee;
        graph[city2][city1].city = city1;
        graph[city2][city1].length = length;
        graph[city2][city1].fee = fee;
    }
    int path[MAX_SIZE];
    int shortestDistance = dijkstra(graph, N, S, D, path);
    int totalFee = 0;
    // 计算路径的总费用
    int city = D;
    while (path[city] != -1) {
        totalFee += graph[city][path[city]].fee;
        city = path[city];
    }
    printf("%d %d\n", shortestDistance, totalFee);
    return 0;
}


目录
相关文章
|
2月前
|
存储 移动开发 算法
数据结构:选择题+编程题(每日一练)
数据结构:选择题+编程题(每日一练)
90 0
|
7月前
|
算法
数据结构刷题训练:用栈实现队列(力扣OJ)
数据结构刷题训练:用栈实现队列(力扣OJ)
40 0
|
7月前
|
存储 算法 C语言
数据结构刷题训练:队列实现栈
数据结构刷题训练:队列实现栈
16 0
|
7月前
数据结构刷题训练——链表篇(三)
数据结构刷题训练——链表篇(三)
26 0
|
2天前
数据结构考试测试编程题
数据结构考试测试编程题
|
8天前
|
存储 安全 Java
Java并发编程中的高效数据结构:ConcurrentHashMap解析
【4月更文挑战第25天】在多线程环境下,高效的数据访问和管理是至关重要的。Java提供了多种并发集合来处理这种情境,其中ConcurrentHashMap是最广泛使用的一个。本文将深入分析ConcurrentHashMap的内部工作原理、性能特点以及它如何在保证线程安全的同时提供高并发性,最后将展示其在实际开发中的应用示例。
|
7月前
|
存储 算法 搜索推荐
数据结构与算法:编程中的基本功
数据结构与算法:编程中的基本功
51 0
|
7月前
数据结构刷题训练——二叉树篇(一)
数据结构刷题训练——二叉树篇(一)
26 0
|
7月前
数据结构刷题训练——链表篇(二)
数据结构刷题训练——链表篇(二)
22 0
|
7月前
|
计算机视觉
数据结构刷题训练——链表篇(一)(下)
数据结构刷题训练——链表篇(一)(下)
21 0