宅配便の配送トラブル

トピックの説明

  • NNありN 個の急行駅は文字列で識別され、一部の駅は道路で接続されています。
  • 各サイトで輸送する荷物がいくつかあり、各サイト間の荷物は繰り返されません。道路上に検問所があり、一部の商品は通行できなくなります。どの商品が通常配送できないかを計算しますか?

説明を入力してください

  • 最初の行に「MNM\quad N」と入力しますMNMMMパッケージとNNN道路情報
  • 0 ≤ M , N ≤ 100 0\leq M,N \leq 1000MさんN100
  • チェックポイント通過が禁止されているパッケージが複数ある場合は、スペースで区切る必要があります。

出力の説明

  • 配信不能パッケージを出力します。package2、package4
  • すべてのパッケージを配送できる場合の出力:none
  • 出力は昇順にソートされます

4 2
package1 A C
package2 A C
package3 B C
package4 A C
A B package1
A C package2

--输出
package2

トピック分析

このトピックは理解するのが非常に難しく、テキストが少ないほど理解するのが難しくなります。

要点を抜粋

  • まず、データ範囲が[ 0 , 1 0 2 ] [0, 10^2]であることに注目してください。[ 0 ,1 02 ]
    • このデータ範囲では、複数回繰り返すことができます
  • んんユースケースなど、より分かりやすくなった Mパッケージ情報
    • package1 A C: パッケージをpackage1サイトA間で配信する必要があることを示しますC
    • ここには、そのようなユースケースがあるかどうか、つまり、サイトからサイトにpackage1 C Aパッケージを届けるという情報が隠されています。CA
      • これはまだ検討する必要があります
  • トピックの説明と入力された説明によると
    • タイトル説明: NNありN 個の配送業者サイトは文字列によって識別され、いくつかのサイト間には道路接続があります。
    • 説明を入力: NNN道路情報
    • この 2 つのNNNも同じ意味ですか?ここは違うはずですが、なぜですか?
      • 道路は 2 つの敷地を結ぶことができるため、
    • すると、入力された記述とユースケースの道路情報から、速達駅間の関係が以下のように分かります。
    • 画像.png
    • ここでは、ユースケースに応じて、package3 B Cキー情報を取得したり、拠点間で速達配送を転送したりすることができます
    • この時点で分析は完了し、問題はグラフ内に有効なパスがあるかどうかを見つける問題に変換されます。

コードを表示

package com.hw;

import java.util.*;

/**
 * desc :
 * <p>
 * create time : 2023/8/17 17:23
 */
public class DeliverPathFinderBetter {
    
    

    public static void main(String[] args) {
    
    
        Scanner in = new Scanner(System.in);

        String[] split = in.nextLine().split(" ");
        // M 个包裹.
        int M = Integer.parseInt(split[0]);
        // N 个道路信息.
        int N = Integer.parseInt(split[1]);

        // 包裹信息,表示包裹需要从 一个站点运输到另一个站点.
        String[][] pkgMsgS = new String[M][];

        for (int i = 0; i < M; i++) {
    
    
            pkgMsgS[i] = in.nextLine().split(" ");
        }

        // 道路信息以及在目标道路上禁止运送的包裹信息.
        String[][] banPkgS = new String[N][];
        for (int i = 0; i < N; i++) {
    
    
            banPkgS[i] = in.nextLine().split(" ");
        }

        deliverPathFinderBetter(pkgMsgS, banPkgS);
    }

    private static void deliverPathFinderBetter(String[][] pkgMsgS, String[][] banPkgS) {
    
    
        // 包裹运送信息--适合用 map 来存储
        Map<String, String[]> deliverMap = new HashMap<>();

        for (String[] pkgMsg : pkgMsgS) {
    
    
            String[] startToEnd = {
    
    pkgMsg[1], pkgMsg[2]};
            //  包裹不能重复,直接 put.
            deliverMap.put(pkgMsg[0], startToEnd);
        }

        // 根据道路信息,构造图数据.
        Map<String, List<String>> graph = new HashMap<>();
        // 用一个map,保存 禁止运输的 包裹信息.
        Map<String, Set<String>> banMap = new HashMap<>();
        // 处理数据.
        for (String[] banPkg : banPkgS) {
    
    
            String site1 = banPkg[0];
            String site2 = banPkg[1];
            String[] bans = Arrays.copyOfRange(banPkg, 2, banPkg.length);
            // 建图数据结构.
            graph.computeIfAbsent(site1, k -> new ArrayList<>()).add(site2);
            graph.computeIfAbsent(site2, k -> new ArrayList<>()).add(site1);

            String key = (site1.charAt(0) - 'A') < (site2.charAt(0) - 'A') ? (site1 + "-" + site2) : (site2 + "-" + site1);
            // 禁止通行的包裹列表
            banMap.computeIfAbsent(key, k -> new HashSet<>()).addAll(Arrays.asList(bans));
        }

        dealPkgS(deliverMap, graph, banMap);
    }

    private static void dealPkgS(Map<String, String[]> deliverMap, Map<String, List<String>> graph, Map<String, Set<String>> banMap) {
    
    
        Set<String> unreachablePackages = new TreeSet<>();
        for (String pkg : deliverMap.keySet()) {
    
    
            // 当前将要运送的包裹是  pkg, 需要运送其从站点  start 到 end  .
            String[] path = deliverMap.get(pkg);
            String start = path[0].charAt(0) - 'A' < path[1].charAt(0) - 'A' ? path[0] : path[1];
            String end = path[0].charAt(0) - 'A' < path[1].charAt(0) - 'A' ? path[1] : path[0];


            // 查看是否存在可通行的路径.
            // 用一个set记录路径——即所到达的站点.
            Set<String> visited = new HashSet<>();
            if(!dfs(pkg, start, end, graph, visited, banMap)) {
    
    
                unreachablePackages.add(pkg);
            }
        }

        if(unreachablePackages.size() == 0) {
    
    
            System.out.println("none");
        } else {
    
    
            for (String unreachablePackage : unreachablePackages) {
    
    
                System.out.print(unreachablePackage + " ");
            }
        }
    }

    private static boolean dfs(String pkg,
                               String start,
                               String end,
                               Map<String, List<String>> graph,
                               Set<String> visited,
                               Map<String, Set<String>> banMap) {
    
    
        if (start.equals(end)) {
    
    
            // 到达了目标站点,那么这个时候返回 true ,表示该包裹可以到达目标站点.
            return true;
        }
        visited.add(start);
        for (String nextSite : graph.getOrDefault(start, Collections.emptyList())) {
    
    
            if(visited.contains(nextSite)) {
    
    
                // 去过的站点跳过.
                continue;
            }
            String key = start.charAt(0) - 'A' < nextSite.charAt(0) - 'A' ? start + "-" + nextSite : nextSite + "-" + start;
            if(banMap.containsKey(key) && banMap.get(key).contains(pkg)) {
    
    
                // 当前路径不允许当前包裹通过.
                continue;
            }
            if(dfs(pkg, nextSite, end, graph, visited, banMap)) {
    
    
                return true;
            }
        }
        return false;
    }

}

おすすめ

転載: blog.csdn.net/GoNewWay/article/details/132361310