自用12-24题C#ACM模式

13. 镂空三角形

题目描述

把一个字符三角形掏空,就能节省材料成本,减轻重量,但关键是为了追求另一种视觉效果。在设计的过程中,需要给出各种花纹的材料和大小尺寸的三角形样板,通过电脑临时做出来,以便看看效果。

输入描述

每行包含一个字符和一个整数n(0<n<41),不同的字符表示不同的花纹,整数n表示等腰三角形的高。显然其底边长为2n-1。如果遇到@字符,则表示所做出来的样板三角形已经够了。

输出描述

每个样板三角形之间应空上一行,三角形的中间为空。行末没有多余的空格。每条结果后需要再多输出一个空行。

输入示例
X 2
A 7
@
输出示例
 X
XXX

      A
     A A
    A   A
   A     A
  A       A
 A         A
AAAAAAAAAAAAA

 

using System;

public class HollowTriangle
{
    public static void Main(string[] args)
    {
        string input;
        while ((input = Console.ReadLine()) != null)
        {
            if (input == "@") break;

            var parts = input.Split(' ');
            char ch = parts[0][0];
            int n = int.Parse(parts[1]);

            // 输出空行用于分隔不同的三角形
            if (n > 0) Console.WriteLine();

            for (int i = 0; i < n; i++)
            {
                // 打印前导空格
                Console.Write(new string(' ', n - i - 1));

                // 打印字符或空格
                if (i == n - 1) // 最底行
                {
                    Console.WriteLine(new string(ch, 2 * n - 1));
                }
                else
                {
                    Console.Write(ch);
                    if (i > 0) // 不是第一行
                    {
                        Console.Write(new string(' ', 2 * i - 1));
                        Console.Write(ch);
                    }
                    Console.WriteLine();
                }
            }
        }

        // 最后再输出一个空行
        Console.WriteLine();
    }
}

14. 句子缩写

题目描述

输出一个词组中每个单词的首字母的大写组合。

输入描述

输入的第一行是一个整数n,表示一共有n组测试数据。(输入只有一个n,没有多组n的输入)
接下来有n行,每组测试数据占一行,每行有一个词组,每个词组由一个或多个单词组成;每组的单词个数不超过10个,每个单词有一个或多个大写或小写字母组成;
单词长度不超过10,由一个或多个空格分隔这些单词。

输出描述

请为每组测试数据输出规定的缩写,每组输出占一行。

输入示例
1
ad dfa     fgs
输出示例
ADF
提示信息

注意:单词之间可能有多个空格

using System;

public class Abbreviation
{
    public static void Main(string[] args)
    {
        // 读取测试数据组数
        int n = int.Parse(Console.ReadLine());

        for (int i = 0; i < n; i++)
        {
            // 读取每组数据
            string line = Console.ReadLine();
            
            // 使用空格分割,处理多余空格
            string[] words = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            // 初始化缩写字符串
            string abbreviation = "";

            // 提取每个单词的首字母并转换为大写
            foreach (string word in words)
            {
                if (word.Length > 0)
                {
                    abbreviation += char.ToUpper(word[0]); // 获取首字母并转为大写
                }
            }

            // 输出缩写
            Console.WriteLine(abbreviation);
        }
    }
}

15. 神秘字符

题目描述

考古学家发现墓碑上有神秘的字符。经过仔细研究,发现原来这是开启古墓入口的方法。
墓碑上有2行字符串,其中第一个串的长度为偶数,现在要求把第2个串插入到第一个串的正中央,如此便能开启墓碑进入墓中。

输入描述

输入数据首先给出一个整数n,表示测试数据的组数。(整个输入中,只有一个n)
然后是n组数据,每组数据2行,每行一个字符串,长度大于0,小于50,并且第一个串的长度必为偶数。

输出描述

请为每组数据输出一个能开启古墓的字符串,每组输出占一行。

输入示例
2
asdf
yu
rtyu
HJK
输出示例
asyudf
rtHJKyu

 

using System;

public class Program
{
    public static void Main()
    {
        // 读取测试数据组数
        int n = int.Parse(Console.ReadLine());

        for (int i = 0; i < n; i++)
        {
            // 读取每组数据
            string str1 = Console.ReadLine();
            string str2 = Console.ReadLine();

            // 计算中间位置
            int mid = str1.Length / 2;

            // 构造新的字符串
            string result = str1.Substring(0, mid) + str2 + str1.Substring(mid);

            // 输出结果
            Console.WriteLine(result);
        }
    }
}

16. 位置互换

题目描述

给定一个长度为偶数位的字符串,请编程实现字符串的奇偶位互换。

输入描述

输入包含多组测试数据。
输入的第一行是一个整数n,表示有测试数据。(整个输入中,只有一个n)
接下来是n组测试数据,保证串长为偶数位(串长<=50)。

输出描述

请为每组测试数据输出奇偶位互换后的结果,每组输出占一行。

输入示例
2
0aa0
bb00
输出示例
a00a
bb00

 

using System;

public class Program
{
    public static void Main()
    {
        // 读取测试数据组数
        int n = int.Parse(Console.ReadLine());

        for (int i = 0; i < n; i++)
        {
            // 读取每组数据
            string input = Console.ReadLine();
            char[] chars = input.ToCharArray();

            // 创建一个字符数组用于存放互换后的结果
            char[] result = new char[chars.Length];

            // 进行奇偶位互换
            for (int j = 0; j < chars.Length; j += 2)
            {
                result[j] = chars[j + 1];     // 偶数位 (索引从0开始)
                result[j + 1] = chars[j];     // 奇数位
            }

            // 输出结果
            Console.WriteLine(new string(result));
        }
    }
}

17. 出栈合法性

题目描述

已知自然数1,2,...,N(1<=N<=100)依次入栈,请问序列C1,C2,...,CN是否为合法的出栈序列。

输入描述

输入包含多组测试数据。
每组测试数据的第一行为整数N(1<=N<=100),当N=0时,输入结束。
第二行为N个正整数,以空格隔开,为出栈序列。

输出描述

对于每组输入,输出结果为一行字符串。
如给出的序列是合法的出栈序列,则输出Yes,否则输出No。

输入示例
5
3 4 2 1 5
5
3 5 1 4 2
0
输出示例
Yes
No

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        while (true)
        {
            // 读取N值
            int n = int.Parse(Console.ReadLine());
            if (n == 0) break;  // 输入结束条件

            // 读取出栈序列
            string[] input = Console.ReadLine().Split();
            int[] popSequence = Array.ConvertAll(input, int.Parse);

            // 检查出栈序列的合法性
            Console.WriteLine(IsValidPopSequence(n, popSequence) ? "Yes" : "No");
        }
    }

    private static bool IsValidPopSequence(int n, int[] popSequence)
    {
        Stack<int> stack = new Stack<int>();
        int current = 1;  // 下一个入栈的自然数

        foreach (int popValue in popSequence)
        {
            // 将所有小于等于popValue的数入栈
            while (current <= n && (stack.Count == 0 || stack.Peek() != popValue))
            {
                stack.Push(current);
                current++;
            }

            // 如果栈顶元素不等于要出栈的值,则不合法
            if (stack.Count == 0 || stack.Pop() != popValue)
            {
                return false;
            }
        }

        return true;
    }
}

18. 链表的基本操作

题目描述

本题考察链表的基本操作。温馨提示:本题较为复杂,需要细心多花一些时间。

输入描述

输入数据只有一组,第一行有n+1个整数,第一个整数是这行余下的整数数目n,后面是n个整数。

这一行整数是用来初始化列表的,并且输入的顺序与列表中的顺序相反,也就是说如果列表中是1、2、3那么输入的顺序是3、2、1。

第二行有一个整数m,代表下面还有m行。每行有一个字符串,字符串是“get”,“insert”,“delete”,“show”中的一种。


 

如果是“get”,代表获得第a个元素。(a从1开始计数)

如果是“delete”,代表删除第a个元素。(a从1开始计数)

如果是“insert”,则其后跟着两个整数a和e,代表在第a个位置前面插入e。(a从1开始计数)

“show”之后没有正数,直接打印链表全部内容。

输出描述

如果获取成功,则输出该元素;

如果删除成功,则输出“delete OK”;

如果获取失败,则输出“get fail”

如果删除失败,则输出“delete fail”

如果插入成功,则输出“insert OK”,否则输出“insert fail”。

如果是“show”,则输出列表中的所有元素,如果列表是空的,则输出“Link list is empty”

注:所有的双引号均不输出。

输入示例
3 3 2 1
21
show
delete 1
show
delete 2
show
delete 1
show
delete 2
insert 2 5
show
insert 1 5
show
insert 1 7
show
insert 2 5
show
insert 3 6
show
insert 1 8
show
get 2
输出示例
1 2 3
delete OK
2 3
delete OK
2
delete OK
Link list is empty
delete fail
insert fail
Link list is empty
insert OK
5
insert OK
7 5
insert OK
7 5 5
insert OK
7 5 6 5
insert OK
8 7 5 6 5
7
提示信息

初始化链表的元素是倒序的,这个使用题目中创建列表的方法(从头部插入)就可以了。

 using System;
using System.Collections.Generic;

public class Node
{
    public int Value;
    public Node Next;

    public Node(int value)
    {
        Value = value;
        Next = null;
    }
}

public class LinkedList
{
    private Node head;

    public LinkedList()
    {
        head = null;
    }

    // 初始化链表
    public void Initialize(List<int> values)
    {
        for (int i = values.Count - 1; i >= 0; i--)
        {
            InsertAtBeginning(values[i]);
        }
    }

    // 在链表前面插入元素
    public void InsertAtBeginning(int value)
    {
        Node newNode = new Node(value);
        newNode.Next = head;
        head = newNode;
    }

    // 获取第a个元素
    public string Get(int a)
    {
        Node current = head;
        int count = 1;

        while (current != null && count < a)
        {
            current = current.Next;
            count++;
        }

        if (current == null)
            return "get fail";
        return current.Value.ToString();
    }

    // 删除第a个元素
    public string Delete(int a)
    {
        if (head == null)
            return "delete fail";

        if (a == 1)
        {
            head = head.Next;
            return "delete OK";
        }

        Node current = head;
        int count = 1;

        while (current.Next != null && count < a - 1)
        {
            current = current.Next;
            count++;
        }

        if (current.Next == null)
            return "delete fail";

        current.Next = current.Next.Next;
        return "delete OK";
    }

    // 在第a个位置前面插入e
    public string Insert(int a, int e)
    {
        if (a < 1)
            return "insert fail";

        if (a == 1)
        {
            InsertAtBeginning(e);
            return "insert OK";
        }

        Node current = head;
        int count = 1;

        while (current != null && count < a - 1)
        {
            current = current.Next;
            count++;
        }

        if (current == null)
            return "insert fail";

        Node newNode = new Node(e);
        newNode.Next = current.Next;
        current.Next = newNode;
        return "insert OK";
    }

    // 显示链表内容
    public string Show()
    {
        if (head == null)
            return "Link list is empty";

        List<int> values = new List<int>();
        Node current = head;

        while (current != null)
        {
            values.Add(current.Value);
            current = current.Next;
        }

        return string.Join(" ", values);
    }
}

public class Program
{
    public static void Main()
    {
        string[] firstLine = Console.ReadLine().Split();
        int n = int.Parse(firstLine[0]);
        List<int> values = new List<int>();

        for (int i = 1; i <= n; i++)
        {
            values.Add(int.Parse(firstLine[i]));
        }

        LinkedList linkedList = new LinkedList();
        linkedList.Initialize(values);

        int m = int.Parse(Console.ReadLine());
        for (int i = 0; i < m; i++)
        {
            string command = Console.ReadLine();
            string[] parts = command.Split();

            switch (parts[0])
            {
                case "get":
                    int a = int.Parse(parts[1]);
                    Console.WriteLine(linkedList.Get(a));
                    break;
                case "delete":
                    a = int.Parse(parts[1]);
                    Console.WriteLine(linkedList.Delete(a));
                    break;
                case "insert":
                    a = int.Parse(parts[1]);
                    int e = int.Parse(parts[2]);
                    Console.WriteLine(linkedList.Insert(a, e));
                    break;
                case "show":
                    Console.WriteLine(linkedList.Show());
                    break;
            }
        }
    }
}

19. 单链表反转

题目描述

根据一个整数序列构造一个单链表,然后将其反转。

例如:原单链表为 2 3 4 5 ,反转之后为5 4 3 2

输入描述

输入包括多组测试数据,每组测试数据占一行,第一个为大于等于0的整数n,表示该单链表的长度,后面跟着n个整数,表示链表的每一个元素。整数之间用空格隔开

输出描述

针对每组测试数据,输出包括两行,分别是反转前和反转后的链表元素,用空格隔开

如果链表为空,则只输出一行,list is empty

输入示例
5 1 2 3 4 5 
0
输出示例
1 2 3 4 5 
5 4 3 2 1 
list is empty
提示信息

本题用数组,也是可有过的,输入一遍数组,然后倒叙输出。不过建议大家用本题来链表操作

using System;
using System.Collections.Generic;

public class Node
{
    public int Value;
    public Node Next;

    public Node(int value)
    {
        Value = value;
        Next = null;
    }
}

public class LinkedList
{
    private Node head;

    public LinkedList()
    {
        head = null;
    }

    // 插入节点到链表
    public void Insert(int value)
    {
        Node newNode = new Node(value);
        if (head == null)
        {
            head = newNode;
        }
        else
        {
            Node current = head;
            while (current.Next != null)
            {
                current = current.Next;
            }
            current.Next = newNode;
        }
    }

    // 反转链表
    public void Reverse()
    {
        Node prev = null;
        Node current = head;

        while (current != null)
        {
            Node nextNode = current.Next;
            current.Next = prev;
            prev = current;
            current = nextNode;
        }
        head = prev;
    }

    // 获取链表内容
    public string GetList()
    {
        if (head == null)
            return "list is empty";

        List<int> values = new List<int>();
        Node current = head;

        while (current != null)
        {
            values.Add(current.Value);
            current = current.Next;
        }

        return string.Join(" ", values);
    }
}

public class Program
{
    public static void Main()
    {
        string line;
        while ((line = Console.ReadLine()) != null && line.Trim() != "")
        {
            string[] parts = line.Split();
            int n = int.Parse(parts[0]);

            LinkedList linkedList = new LinkedList();

            if (n > 0)
            {
                for (int i = 1; i <= n; i++)
                {
                    linkedList.Insert(int.Parse(parts[i]));
                }

                // 输出反转前的链表
                Console.WriteLine(linkedList.GetList());

                // 反转链表
                linkedList.Reverse();

                // 输出反转后的链表
                Console.WriteLine(linkedList.GetList());
            }
            else
            {
                Console.WriteLine("list is empty");
            }
        }
    }
}
 

 

21. 构造二叉树

题目描述

给你一棵二叉树的前序遍历和中序遍历结果,要求你写出这棵二叉树的后序遍历结果。

输入描述

输入包含多组测试数据。每组输入包含两个字符串,分别表示二叉树的前序遍历和中序遍历结果。每个字符串由不重复的大写字母组成。

输出描述

对于每组输入,输出对应的二叉树的后续遍历结果。

输入示例
DBACEGF ABCDEFG
BCAD CBAD
输出示例
ACBFGED
CDAB

 

using System;
using System.Collections.Generic;

public class TreeNode
{
    public char Value;
    public TreeNode Left;
    public TreeNode Right;

    public TreeNode(char value)
    {
        Value = value;
        Left = null;
        Right = null;
    }
}

public class Program
{
    // 构造二叉树
    public static TreeNode BuildTree(string preorder, string inorder)
    {
        if (preorder.Length == 0 || inorder.Length == 0)
            return null;

        char rootValue = preorder[0]; // 前序的第一个元素是根节点
        TreeNode root = new TreeNode(rootValue);

        // 找到根节点在中序遍历中的索引
        int rootIndex = inorder.IndexOf(rootValue);

        // 递归构建左子树和右子树
        root.Left = BuildTree(preorder.Substring(1, rootIndex), inorder.Substring(0, rootIndex));
        root.Right = BuildTree(preorder.Substring(rootIndex + 1), inorder.Substring(rootIndex + 1));

        return root;
    }

    // 后序遍历
    public static string PostOrderTraversal(TreeNode node)
    {
        if (node == null)
            return "";

        // 先访问左子树,再访问右子树,最后访问根节点
        return PostOrderTraversal(node.Left) + PostOrderTraversal(node.Right) + node.Value;
    }

    public static void Main()
    {
        string line;
        while ((line = Console.ReadLine()) != null && line.Trim() != "")
        {
            string[] parts = line.Split();
            string preorder = parts[0];
            string inorder = parts[1];

            // 构造二叉树
            TreeNode root = BuildTree(preorder, inorder);
            // 输出后序遍历结果
            string postOrderResult = PostOrderTraversal(root);
            Console.WriteLine(postOrderResult);
        }
    }
}

22. 二叉树的遍历

题目描述

给出一个n个节点的二叉树,请求出二叉树的前序遍历,中序遍历和后序遍历。

输入描述

题目包含多行输入,第一行为一个整数 N,表示二叉树的节点总数,后面将有 N 行对应于二叉树的 N 个节点的信息。

每行的数据格式遵循如下规则:

每行开始是该节点的标识符,代表二叉树中具体的一个节点。

节点标识符之后是两个数字,分别表示该节点的左孩子和右孩子的序号。序号根据输入顺序从 1 开始自动分配,即第一个输入的节点序号为 1,第二个为 2,以此类推。

若某个节点的左孩子或右孩子序号为 0,则表示该节点不存在相应的左孩子或右孩子。

输出描述

共三行,第一行为二叉树的前序遍历,第二行为中序遍历,第三行为后序遍历

输入示例
7
F 2 3
C 4 5
E 0 6
A 0 0
D 7 0
G 0 0
B 0 0
输出示例
FCADBEG
ACBDFEG
ABDCGEF
提示信息

样例输入解释如下: 首行数字 7 表示二叉树共有 7 个节点。接下来的行按序提供每个节点的信息,

格式为:标识符 左孩子序号 右孩子序号。节点序号自动从 1 依次递增,对应输入的行顺序。

例如:

F 2 3 表示标识符为 F 的节点(序号为 1)有左孩子(序号为 2)和右孩子(序号为 3);

E 0 6 表示标识符为 E 的节点(序号为 3)无左孩子,有右孩子(序号为 6)。

由于 F 的右孩子是序号为 3 的节点,而 E 的序号刚好为 3,所以 F 的右孩子就是 E。

 

using System;
using System.Collections.Generic;

public class TreeNode
{
    public char Value;
    public TreeNode Left;
    public TreeNode Right;

    public TreeNode(char value)
    {
        Value = value;
        Left = null;
        Right = null;
    }
}

public class Program
{
    private static List<TreeNode> nodes = new List<TreeNode>();

    // 构造树
    public static void BuildTree(int n)
    {
        for (int i = 0; i < n; i++)
        {
            string[] parts = Console.ReadLine().Split();
            char value = parts[0][0];
            int leftIndex = int.Parse(parts[1]) - 1; // 转为0索引
            int rightIndex = int.Parse(parts[2]) - 1; // 转为0索引
            
            TreeNode node = new TreeNode(value);
            nodes.Add(node);

            if (leftIndex >= 0)
                node.Left = nodes[leftIndex];
            if (rightIndex >= 0)
                node.Right = nodes[rightIndex];
        }
    }

    // 前序遍历
    public static string PreOrder(TreeNode node)
    {
        if (node == null)
            return "";
        return node.Value + PreOrder(node.Left) + PreOrder(node.Right);
    }

    // 中序遍历
    public static string InOrder(TreeNode node)
    {
        if (node == null)
            return "";
        return InOrder(node.Left) + node.Value + InOrder(node.Right);
    }

    // 后序遍历
    public static string PostOrder(TreeNode node)
    {
        if (node == null)
            return "";
        return PostOrder(node.Left) + PostOrder(node.Right) + node.Value;
    }

    public static void Main()
    {
        int n = int.Parse(Console.ReadLine());
        BuildTree(n);

        // 假设根节点为第一个节点
        TreeNode root = nodes[0];

        // 输出遍历结果
        Console.WriteLine(PreOrder(root));
        Console.WriteLine(InOrder(root));
        Console.WriteLine(PostOrder(root));
    }
}

23. 二叉树的高度

题目描述

现给定一棵二叉树的先序遍历序列和中序遍历序列,要求你计算该二叉树的高度。

输入描述

输入包含多组测试数据,每组输入首先给出正整数N(<=50),为树中结点总数。下面2行先后给出先序和中序遍历序列,均是长度为N的不包含重复英文字母(区别大小写)的字符串。

输出描述

对于每组输入,输出一个整数,即该二叉树的高度。

输入示例
9
ABDFGHIEC
FDHGIBEAC
7
Abcdefg
gfedcbA
输出示例
5
7

 

using System;

public class TreeNode
{
    public char Value;
    public TreeNode Left;
    public TreeNode Right;

    public TreeNode(char value)
    {
        Value = value;
        Left = null;
        Right = null;
    }
}

public class Program
{
    // 构建二叉树
    public static TreeNode BuildTree(string preorder, string inorder)
    {
        if (string.IsNullOrEmpty(preorder) || string.IsNullOrEmpty(inorder))
            return null;

        char rootValue = preorder[0];
        TreeNode root = new TreeNode(rootValue);

        int rootIndexInInorder = inorder.IndexOf(rootValue);
        string leftInorder = inorder.Substring(0, rootIndexInInorder);
        string rightInorder = inorder.Substring(rootIndexInInorder + 1);

        string leftPreorder = preorder.Substring(1, leftInorder.Length);
        string rightPreorder = preorder.Substring(1 + leftInorder.Length);

        root.Left = BuildTree(leftPreorder, leftInorder);
        root.Right = BuildTree(rightPreorder, rightInorder);

        return root;
    }

    // 计算树的高度
    public static int CalculateHeight(TreeNode node)
    {
        if (node == null)
            return 0;
        
        int leftHeight = CalculateHeight(node.Left);
        int rightHeight = CalculateHeight(node.Right);
        
        return Math.Max(leftHeight, rightHeight) + 1;
    }

    public static void Main()
    {
        string line;
        while ((line = Console.ReadLine()) != null)
        {
            int n = int.Parse(line);
            string preorder = Console.ReadLine();
            string inorder = Console.ReadLine();

            TreeNode root = BuildTree(preorder, inorder);
            int height = CalculateHeight(root);
            Console.WriteLine(height);
        }
    }
}

24. 最长公共子序列

题目描述

给你一个序列X和另一个序列Z,当Z中的所有元素都在X中存在,并且在X中的下标顺序是严格递增的,那么就把Z叫做X的子序列。
例如:Z=是序列X=的一个子序列,Z中的元素在X中的下标序列为<1,2,4,6>。
现给你两个序列X和Y,请问它们的最长公共子序列的长度是多少?

输入描述

输入包含多组测试数据。每组输入占一行,为两个字符串,由若干个空格分隔。每个字符串的长度不超过100。

输出描述

对于每组输入,输出两个字符串的最长公共子序列的长度。

输入示例
abcfbc abfcab
programming contest 
abcd mnp
输出示例
4
2
0

 

using System;

public class Program
{
    public static int LongestCommonSubsequence(string x, string y)
    {
        int m = x.Length;
        int n = y.Length;

        // 创建一个二维数组来存储动态规划结果
        int[,] dp = new int[m + 1, n + 1];

        // 填充dp数组
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if (x[i - 1] == y[j - 1])
                {
                    dp[i, j] = dp[i - 1, j - 1] + 1; // 字符相同
                }
                else
                {
                    dp[i, j] = Math.Max(dp[i - 1, j], dp[i, j - 1]); // 字符不同
                }
            }
        }

        return dp[m, n]; // 返回LCS的长度
    }

    public static void Main()
    {
        string line;
        while ((line = Console.ReadLine()) != null)
        {
            string[] parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length != 2)
                continue; // 如果输入格式不对则跳过

            string x = parts[0];
            string y = parts[1];
            int length = LongestCommonSubsequence(x, y);
            Console.WriteLine(length);
        }
    }
}

25. 最爱的城市

题目描述

一天小明捧着一本世界地图在看,突然小明拿起笔,将他最爱的那些城市标记出来,并且随机的将这些城市中的某些用线段两两连接起来。
小明量出了每条线段的长度,现在小明想知道在这些线段组成的图中任意两个城市之间的最短距离是多少。

输入描述

输入包含多组测试数据。
每组输入第一行为两个正整数n(n<=10)和m(m<=n*(n-1)/2),n表示城市个数,m表示线段个数。
接下来m行,每行输入三个整数a,b和l,表示a市与b市之间存在一条线段,线段长度为l。(a与b不同)
每组最后一行输入两个整数x和y,表示问题:x市与y市之间的最短距离是多少。(x与y不同)
城市标号为1~n,l<=20。

输出描述

对于每组输入,输出x市与y市之间的最短距离,如果x市与y市之间非连通,则输出“No path”。

输入示例
4 4
1 2 4
1 3 1
1 4 1
2 3 1
2 4
输出示例
3

 

using System;
using System.Collections.Generic;

public class Program
{
    private const int MaxValue = int.MaxValue;

    public static void Main()
    {
        string line;
        while ((line = Console.ReadLine()) != null)
        {
            string[] parts = line.Split();
            if (parts.Length < 2)
                continue; // 如果输入格式不对则跳过
            
            int n = int.Parse(parts[0]);
            int m = int.Parse(parts[1]);

            // 初始化图
            var graph = new Dictionary<int, List<(int, int)>>();
            for (int i = 1; i <= n; i++)
            {
                graph[i] = new List<(int, int)>();
            }

            // 读取边
            for (int i = 0; i < m; i++)
            {
                string[] edgeParts = Console.ReadLine().Split();
                int a = int.Parse(edgeParts[0]);
                int b = int.Parse(edgeParts[1]);
                int l = int.Parse(edgeParts[2]);

                graph[a].Add((b, l)); // a -> b
                graph[b].Add((a, l)); // b -> a (无向图)
            }

            // 读取查询
            string[] queryParts = Console.ReadLine().Split();
            int x = int.Parse(queryParts[0]);
            int y = int.Parse(queryParts[1]);

            // 计算最短路径
            var result = Dijkstra(graph, n, x, y);
            Console.WriteLine(result == MaxValue ? "No path" : result.ToString());
        }
    }

    private static int Dijkstra(Dictionary<int, List<(int, int)>> graph, int n, int start, int end)
    {
        var distances = new int[n + 1];
        var visited = new bool[n + 1];
        for (int i = 1; i <= n; i++)
        {
            distances[i] = MaxValue;
            visited[i] = false;
        }
        distances[start] = 0;

        for (int i = 1; i <= n; i++)
        {
            int u = -1;
            // 找到未访问节点中距离最小的
            for (int j = 1; j <= n; j++)
            {
                if (!visited[j] && (u == -1 || distances[j] < distances[u]))
                {
                    u = j;
                }
            }

            if (u == -1 || distances[u] == MaxValue) break; // 所有可达的节点都已访问完

            visited[u] = true;

            foreach (var (v, length) in graph[u])
            {
                if (distances[u] + length < distances[v])
                {
                    distances[v] = distances[u] + length; // 更新最短距离
                }
            }
        }

        return distances[end];
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值