数据结构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;
}


目录
相关文章
|
1月前
|
存储 缓存 分布式计算
数据结构与算法学习一:学习前的准备,数据结构的分类,数据结构与算法的关系,实际编程中遇到的问题,几个经典算法问题
这篇文章是关于数据结构与算法的学习指南,涵盖了数据结构的分类、数据结构与算法的关系、实际编程中遇到的问题以及几个经典的算法面试题。
29 0
数据结构与算法学习一:学习前的准备,数据结构的分类,数据结构与算法的关系,实际编程中遇到的问题,几个经典算法问题
|
2月前
|
存储 索引 Python
Python编程的常用数据结构—列表
Python编程的常用数据结构—列表
|
2月前
|
存储 索引 Python
Python编程的常用数据结构—列表 原创
Python编程的常用数据结构—列表 原创
|
2月前
|
Python
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
28 0
|
2月前
|
算法 开发者 计算机视觉
Python并查集:数据结构界的肌肉男,让你在编程路上无所畏惧!
在编程的浩瀚宇宙中,数据结构如同基石,构建了解决问题的坚实框架。而并查集(Union-Find),这位数据结构界的“肌肉男”,以其独特的魅力和强大的功能,让无数开发者在面对复杂关系处理时,都能感受到前所未有的从容与自信。今天,就让我们一同揭开并查集的神秘面纱,看看它是如何成为你编程路上的得力助手的。
31 0
|
2月前
|
算法 程序员 计算机视觉
Python并查集:数据结构界的肌肉男,让你在编程路上无所畏惧!
并查集,一种处理不相交集合合并与查询的数据结构,被誉为编程的“肌肉男”。它提供Find(找根节点)和Union(合并集合)操作,常用于好友关系判断、图像处理、集合合并等。Python实现中,路径压缩和按秩合并优化效率。并查集的高效性能使其成为解决问题的强大工具,助力程序员应对复杂挑战。
29 0
|
3月前
|
存储 C#
揭秘C#.Net编程秘宝:结构体类型Struct,让你的数据结构秒变高效战斗机,编程界的新星就是你!
【8月更文挑战第4天】在C#编程中,结构体(`struct`)是一种整合多种数据类型的复合数据类型。与类不同,结构体是值类型,意味着数据被直接复制而非引用。这使其适合表示小型、固定的数据结构如点坐标。结构体默认私有成员且不可变,除非明确指定。通过`struct`关键字定义,可以包含字段、构造函数及方法。例如,定义一个表示二维点的结构体,并实现计算距离原点的方法。使用时如同普通类型,可通过实例化并调用其成员。设计时推荐保持结构体不可变以避免副作用,并注意装箱拆箱可能导致的性能影响。掌握结构体有助于构建高效的应用程序。
115 7
|
4月前
|
Python
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
【7月更文挑战第18天】并查集,数据结构超级英雄,用于不相交集合的合并与查询。Python实现包括初始化、查找根节点和合并操作。应用广泛,如社交网络分析、图论问题、集合划分等。示例代码展示了解决岛屿数量问题,统计连通的“1”单元格数。掌握并查集,提升编程效率,解决复杂问题。
52 6
|
4月前
|
算法 程序员 计算机视觉
Python并查集:数据结构界的肌肉男,让你在编程路上无所畏惧!
【7月更文挑战第16天】并查集,一种处理不相交集合合并与查询的数据结构,被誉为编程的“肌肉男”。它提供Find(找根节点)和Union(合并集合)操作,常用于好友关系判断、图像处理、集合合并等。Python实现中,路径压缩和按秩合并优化效率。并查集的高效性能使其成为解决问题的强大工具,助力程序员应对复杂挑战。
47 0
|
4月前
|
安全 调度 Python
Python堆与优先队列:不只是数据结构,更是你编程路上的超级加速器!
【7月更文挑战第8天】Python的heapq模块和queue.PriorityQueue提供堆与优先队列功能。堆,作为完全二叉树,支持排序性质,heapq用于单线程操作;PriorityQueue在多线程中保证安全。通过示例展示了如何插入、删除任务,以及在多线程任务调度中的应用。堆与优先队列是高效编程的关键工具,提升代码性能与并发处理能力。
39 0

热门文章

最新文章