数据结构实验四

目录

问题A:机器人王国里的路径长度

问题B:从源点开始的最短路径

问题C:最少天数

问题D:寻找第二小的数

问题E:按十进制给各位排序

问题F:奇偶数的排序


问题A:机器人王国里的路径长度


题目描述
在一个机器人王国里,围绕首都分N层构建卫星城市。以首都为圆心,以路相连分出两个卫星城在第一个层,然后每个卫星城又有路相连分出两个卫星城在下一层,但每条路的长度不同。第N层的卫星城不再分出新的卫星城。现在人类只探知到所有直接相连的城市间的路程,你能计算某个卫星城到达首都的路程吗?
输入
第一行为N,表示机器人王国里有N层卫星城,N最大为10。从第二行开始,共2N+1-2行,每行分别是城市的代号到其分出的卫星城的代号和它们间的路程。 代号用若干个字母表示,直连路程最大为100。最后一行是某卫星城的代号。
输出
根据最后一行的卫星城代号,求该卫星城到首都的路程。
样例输入 
2
A F 20
B D 100
G A 5
G B 10
A C 6
B E 30
D
样例输出 
110

#include<bits/stdc++.h>

using namespace std;

const int N=10000;

map<string,string>parent;

map<string,int>data;

int main()

{

    int n;

    cin>>n;

    for(int i=0;i<pow(2,n+1)-2;i++)

    {

        string m,n;

        int len;

        cin>>m>>n>>len;

        parent[n]=m;

        data[n]=len;

    }

    string p;

    cin>>p;

    int ans=0;

    while(parent.count(p))

    {

        ans+=data[p];

        p=parent[p];

    }

    cout<<ans;

    return 0;

}


问题B:从源点开始的最短路径


题目描述
给你一个有向图的所有顶点有序对,顶点用1~n编号,每个有序对描述有向边,请编程求解从1到任意一个顶端i的最短路径长度。
输入
第一行是n和m,分别表示顶点数(n<100)和有向边数(m<100)。
从第二行开始n行,对应三个数,前两个表示顶点有序对,第三个数表示边的权。
最后一行i,表示要求解从1到顶点i的最短路径长度。
输出
从1到顶点i的最短路径长度。
样例输入 
4 5
1 2 4
1 3 6
2 3 1
3 4 6
2 4 7
3
样例输出 
5

#include<bits/stdc++.h>

using namespace std;

const int N = 100;

int n,m;

int dist[N],g[N][N];

bool st[N];

  

int dijkstra(int ans)

{

    memset(dist,0x3f,sizeof dist); 

    dist[1] = 0;

    for(int i=0;i<ans-1;i++)

    {

        int t = -1;

        for(int j=1;j<=ans;j++)

        {

            if(!st[j]&&(t==-1||dist[t]>dist[j]))

                t = j;

        }

        for(int j = 1;j<=ans;j++)

        {

            dist[j] = min(dist[j],dist[t]+g[t][j]);

        }

        st[t] = true;

    }

    if(dist[ans] == 0x3f3f3f3f) return -1;

    return dist[ans];

}

  

int main()

{

    cin>>n>>m;

    memset(g,0x3f,sizeof g);

    while(m--)

    {

        int a,b,c;

        cin>>a>>b>>c;

        g[a][b] = min(g[a][b],c);

    }

    int popurse;

    cin>>popurse;

    int t = dijkstra(popurse);

    cout<<t;

    return 0;

}

问题C:最少天数


题目描述
有一项大的工程,工程中有许多前后依赖的子任务,每个子任务都规划了完成需要的天数,假设给出用字母表示的事件结点,整个工程的开始事件用A表示,工程结束事件用Z表示,用事件结点有序对表示一个子任务的开始和结束,并给出每个子任务完成需要的天数。请编程求解完成这个工程的最短天数。
输入
第一行是事件结点的个数N(N<26)和子任务数M。
从第二行开始M行,每行是子任务的开始事件和结束事件以及完成该子任务所需天数。
输出
完成该工程所需的最少天数。
样例输入 
4 3
A B 6
B Z 2
A Z 5
样例输出 
8

#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
#include <limits>

using namespace std;

// 定义图的边
struct Edge {
    char destination;
    int weight;
};

// 计算完成工程的最短天数
int calculateShortestTime(const unordered_map<char, vector<Edge>>& graph) {
    unordered_map<char, int> inDegree;
    unordered_map<char, int> earliestStartTime;

    // 统计每个事件的入度
    for (const auto& node : graph) {
        char currentNode = node.first;
        inDegree[currentNode] = 0;
        earliestStartTime[currentNode] = -1; // 初始化最早开始时间为-1
    }

    for (const auto& node : graph) {
        char currentNode = node.first;
        for (const Edge& edge : node.second) {
            char nextNode = edge.destination;
            inDegree[nextNode]++;
        }
    }

    // 初始化起点的最早开始时间为0
    earliestStartTime['A'] = 0;

    // 使用拓扑排序计算每个事件的最早开始时间
    queue<char> q;
    q.push('A');

    while (!q.empty()) {
        char currentNode = q.front();
        q.pop();

        auto it = graph.find(currentNode);
        if (it == graph.end()) {
            continue;
        }

        for (const Edge& edge : it->second) {
            char nextNode = edge.destination;
            int nextStartTime = earliestStartTime[currentNode] + edge.weight;
            earliestStartTime[nextNode] = max(earliestStartTime[nextNode], nextStartTime);

            if (--inDegree[nextNode] == 0) {
                q.push(nextNode);
            }
        }
    }

    // 返回工程的最短天数
    return earliestStartTime['Z'];
}

int main() {
    int N, M;
    cin >> N >> M;

    unordered_map<char, vector<Edge>> graph;

    // 读取子任务信息
    for (int i = 0; i < M; ++i) {
        char startNode, endNode;
        int weight;
        cin >> startNode >> endNode >> weight;
        graph[startNode].push_back({ endNode, weight });
    }

    int shortestTime = calculateShortestTime(graph);
    cout << shortestTime << endl;

    return 0;
}

问题D:寻找第二小的数


题目描述
求n个整数中第二小的数。
相同的整数看成一个数。比如,有5个数分别是1,1,3,4,5,那么第二小的数就是3。
输入
输入包含多组测试数据。输入的第一行是一个整数C,表示有C组测试数据;
每组测试数据的第一行是一个整数n,表示本组测试数据有n个整数(2<=n<=10),接着一行是n个整数(每个数均小于100)。
输出
为每组测试数据输出第二小的整数,如果不存在第二小的整数则输出“NO”,每组输出占一行。
样例输入 
3
2
1 2
5
1 1 3 4 5
3
1 1 1
样例输出 
2
3
NO

#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
  int c,i,n,a[11],d;
  scanf("%d",&c);
  while(c--)
  {
    d=0;
    scanf("%d",&n);
    for(i=0;i<n;i++)
      scanf("%d",&a[i]);
    sort(a,a+n);
    for(i=0;i<n-1;i++)
      if(a[i]!=a[i+1])
     {
      printf("%d\n",a[i+1]);
      d++;
      break;
     }
    if(d==0)
      printf("NO\n");
  }
  return 0;
}

问题E:按十进制给各位排序


题目描述
对于给定的正整数序列,按照每个数的十进制形式各个位上的数之和从大到小排序,各个位上的数和相同的按照本身大小排序,大的在前,小的在后。
输入
第一行 1 个整数 n,表示序列的大小。( 0 < n ≤ 1000) 第二行 n 个正整数,表示序列的每个数,每个数不大于 100000000。
输出
输出按照题目要求排序后的序列。
样例输入 

17 26 9 13 88 22
样例输出 
88 9 26 17 22 13

#include <iostream>
using namespace std;
 
int sum(int n)
{
    int s = 0;
    while(n>0)
    {
        s+=n%10;
        n/=10;
    }
    return s;
}
int main()
{
    int i,j,t,n,a[1000],b[1000];
    cin>>n;
    for(i=0;i<n;i++)
    {
        cin>>a[i];
        b[i] = sum(a[i]);
    }
    for(i=0;i<n-1;i++)
    {
        for(j=0;j<n-i-1;j++)
        {
            if((b[j] < b[j+1]) || ((b[j] == b[j+1]) && (a[j] < a[j+1])))
            {
                t = b[j];
                b[j] = b[j+1];
                b[j+1] = t;
                t = a[j];
                a[j] = a[j+1];
                a[j+1] = t;
            }
        }
    }
    for(i=0;i<n;i++)
        cout<<a[i]<<" ";
    return 0;
}

问题F:奇偶数的排序


题目描述
给你10个正整数,其中5个奇数、5个偶数,先递减排奇数,然后再递增排偶数。请编程实现。
输入
一行10个正整数(int类型范围)。
输出
先递减排5个奇数,然后再递增排5个偶数,各个数之间有一个空格间隔。
样例输入 
1 2 3 4 5 6 7 8 10 9
样例输出 
9 7 5 3 1 2 4 6 8 10

#include<iostream>
#include<algorithm>
#define N 10
using namespace std;
bool comp1(const int &a,const int &b){
    return a>b;
}
bool comp2(const int &a,const int &b){
    return a<b; 
}
int main(){
     int a[N];
      
     int i;
     while(cin>>a[0]>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6]>>a[7]>>a[8]>>a[9]){
           int od=0,ev=0;
           int odd[N],even[N];
          for(i=0;i<N;i++){
             if(a[i]%2==0){
                 even[ev++]=a[i];
                  
             }
             else
                 odd[od++]=a[i];
          }
          sort(even,even+ev,comp2);
          sort(odd,odd+od,comp1);
           
          if(od){
            cout<<odd[0];
            for(int i=1;i<od;i++) cout<<' '<<odd[i];
            for(int i=0;i<ev;i++) cout<<' '<<even[i];
            cout<<endl;
        }else {
            cout<<even[0];
            for(int i=1;i<ev;i++) cout<<' '<<even[i];
            cout<<endl;
        }
 
     }     
     return 0;
      
      
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值