"Concours d'algorithmes · 300 questions rapides" Une question par jour : "Conversion d'unités"

" Concours d'algorithmes : 300 questions rapides " sera publié en 2024 et est un cahier d'exercices auxiliaire pour le " Concours d'algorithmes " . Toutes les questions sont placées dans le JO New Online Judge
auto-construit . Les codes sont donnés en trois langages : C/C++, Java et Python. Les sujets sont principalement des sujets de niveau moyen à bas et conviennent aux étudiants débutants et avancés.


" Conversion d'unité ", lien : http://oj.ecustacm.cn/problem.php?id=2136

Description des questions

[Description du problème] Étant donné n ensembles de relations de conversion d'unités et q ensembles de requêtes, chaque fois qu'une certaine unité est convertie en une autre unité.
   Relation de conversion d'unité : 1 <unitéA> = <valeur> <unitéB>. Indique qu'une unité de <unitA> à gauche équivaut à des unités <value> de <unitB>.
   Format de requête : <valeur> <unitéA> à <unitéB>. Demande combien d’unités de <unitB> sont équivalentes aux unités <value> de <unitA>.
[Format d'entrée] Saisissez la première ligne d'entiers positifs n, q. 1≤n≤100,1≤q≤10000.
   Les n lignes suivantes, chaque ligne est : 1 <unitA> = <value> <unitB>.
   Viennent ensuite q lignes, dont chacune est : <unitA> à <unitB>.
   Où <value> est un nombre à virgule flottante v, appartenant à l'intervalle [0,001,1000], avec jusqu'à 9 chiffres après la virgule décimale.
   <unitA>, <unitB> contiennent jusqu'à 20 lettres minuscules.
   Il est garanti que les unités de la requête sont définies dans au moins une équation de conversion d'unités. Chaque unité peut être convertie en n’importe quelle autre unité d’une seule manière au maximum.
[Format de sortie] Pour chaque requête, affichez la valeur de l'unité demandée, ou "impossible" si la requête ne peut pas recevoir de réponse.
   L'erreur absolue ou l'erreur relative entre le résultat de sortie et la réponse standard ne dépasse pas 10-6 et est considérée comme correcte.
【Échantillon d'entrée】

样例14 3
1 foot = 12 inch
1 yard = 3 foot
1 meter = 100 centimeter
1 centimeter = 10 millimeter
750 millimeter to meter
42 yard to inch
10 meter to foot

样例24 3
1 fortnight = 14 day
1 microcentury = 0.036525 day
1 microcentury = 1000 nanocentury
1 week = 7 day
22.2 fortnight to nanocentury
2.5 nanocentury to week
3.14 day to fortnight

样例310 2
1 micrometer = 1000 nanometer
1 millimeter = 1000 micrometer
1 meter = 1000 millimeter
1 kilometer = 1000 meter
1 megameter = 1000 kilometer
1 lightsecond = 299.792458 meter
1 lightminute = 60 lightsecond
1 lighthour = 60 lightminute
1 lightday = 24 lighthour
1 lightyear = 365.25 lightday
42 nanometer to lightyear
42 lightyear to nanometer

【Échantillon de sortie】

样例10.75
1512
impossible

样例28509240.2464065708427
1.3044642857142857142e-05
0.22428571428571428572

样例34.439403502903384947e-18
3.9735067984839359997e+20

répondre

   Ce problème est directement modélisé comme un problème de chemin sur le graphe. Considérez l'unité comme un point et la valeur de conversion comme une arête, puis toutes les expressions de relation de conversion d'unité sont converties en un graphique dans lequel se trouvent des sous-graphiques interconnectés.
   Lors d'une requête, si deux points (deux unités) se trouvent sur un sous-graphe connecté, recherchez un chemin et calculez le produit des chemins (multipliez les valeurs de conversion de toutes les arêtes de ce chemin) pour obtenir la réponse ; s'ils ne le sont pas sur un sous-graphe connecté On, sortie "impossible".
   Cette question nécessite simplement de trouver un chemin, pas nécessairement le chemin le plus court. Quel algorithme de chemin est utilisé ? Si vous recherchez un chemin sur un graphique normal, vous devez utiliser un algorithme comme celui de Dijkstra. Si vous utilisez DFS, vous devrez peut-être rechercher un grand nombre de chemins, ce qui entraînera un délai d'attente.
   Quelle est la forme du sous-graphe connecté dans cette question ? La question limite "Chaque unité peut être convertie en n'importe quelle autre unité d'une manière au plus", ce qui signifie qu'il n'y a qu'un seul chemin entre deux points, ce qui signifie que ce sous-graphe connecté est un arbre. Dans un arbre, il n'y a qu'un seul chemin entre deux points. L'encodage DFS est le plus simple. La complexité d'un calcul de chemin est O(n).
   Lors de la construction d'un graphique, une relation de conversion est une arête dirigée, mais elle peut être convertie dans le sens opposé. Par exemple, "1 quinzaine = 14 jours" devient à son tour "1 jour = 1/14 quinzaine". Un tel bord dirigé est en réalité un bord bidirectionnel, ou considéré comme un bord non orienté.
[Points clés] Chemin DFS.

Code C++

   Les points clés du code sont : (1) Utilisez la table de contiguïté la plus couramment utilisée pour stocker le graphique ; (2) Utilisez map pour convertir l'unité en un nombre unique ; (3) Utilisez dfs pour rechercher un chemin et calculer le produit des chemins.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
map<string, int>id;             //用map把单位转为唯一的数字
int cnt = 0;
int get_id(string s){
    
               //查询单位对应的数字
    if(id.count(s)) return id[s];
    return id[s] = ++cnt;
}
vector<pair<int,ld>> G[110];           //用邻接表存图
ld dfs(int s, int fa, int t, ld ans){
    
      //搜起点s到终点t的路径。fa是s的上一个点
    if(s == t)return ans;              //到达终点
    for(auto now : G[s]){
    
    
        int v = now.first;
        ld w = now.second;
        if(v == fa) continue;          //不回头
        ld now_ans = dfs(v, s, t, ans * w);
        if(now_ans > 0) return now_ans;  //返回答案
    }
    return -1;                         //没搜到路径
}
int main(){
    
    
    int n, q;   cin >> n >> q;
    while(n--){
    
    
        ld va, vb;
        string sa, sb, _;                       // _ 是 ‘=’
        cin >> va >> sa >> _ >> vb >> sb;
        G[get_id(sa)].push_back(make_pair(get_id(sb), vb));        //双向边
        G[get_id(sb)].push_back(make_pair(get_id(sa), 1.0 / vb));
    }
    while(q--){
    
    
        ld va;
        string sa, sb, _;
        cin >> va >> sa >> _ >> sb;
        auto ans = dfs(get_id(sa), -1, get_id(sb), va);
        if(ans > 0) printf("%.10Lf\n", ans);   //注意long double的输出格式
        else        printf("impossible\n");
    }
    return 0;
}

Code Java

import java.util.*;
public class Main {
    
    
    static Map<String, Integer> id = new HashMap<>();
    static int cnt = 0;
    static List<Pair<Integer, Double>>[] G = new ArrayList[110];    
    static int get_id(String s) {
    
    
        if (id.containsKey(s)) return id.get(s);
        cnt++;
        id.put(s, cnt);
        return cnt;
    }     
    static double dfs(int s, int fa, int t, double ans) {
    
    
        if (s == t) return ans;
        for (Pair<Integer, Double> now : G[s]) {
    
    
            int v = now.first;
            double w = now.second;
            if (v == fa) continue;
            double now_ans = dfs(v, s, t, ans * w);
            if (now_ans > 0) return now_ans;
        }
        return -1;
    }     
    public static void main(String[] args) {
    
    
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), q = sc.nextInt();
        for (int i = 1; i <= Math.min(n+n, 101); i++) G[i] = new ArrayList<>();
        while (n-- > 0) {
    
    
            double va, vb;
            String sa, sb, e;
            va = sc.nextDouble();
            sa = sc.next();
            e = sc.next();
            vb = sc.nextDouble();
            sb = sc.next();
            G[get_id(sa)].add(new Pair<>(get_id(sb), vb));
            G[get_id(sb)].add(new Pair<>(get_id(sa), 1 / vb));
        }
        while (q-- > 0) {
    
    
            double va;
            String sa, sb, e;
            va = sc.nextDouble();
            sa = sc.next();
            e = sc.next();
            sb = sc.next();
            double ans = dfs(get_id(sa), -1, get_id(sb), va);
            if (ans > 0) System.out.printf("%.10f\n", ans);
            else System.out.println("impossible");
        }
    }
} 
class Pair<A, B> {
    
    
    A first;
    B second;     
    Pair(A first, B second) {
    
    
        this.first = first;
        this.second = second;
    }
}

Code Python

import sys
sys.setrecursionlimit(1000000)
id = {
    
    }  #用字典把单位转为唯一的数字
cnt = 0
G = [[] for _ in range(200)]  # 邻接表存图
def get_id(s):
    global cnt
    if s in id:  return id[s]
    cnt += 1
    id[s] = cnt
    return cnt
def dfs(s, fa, t, ans):
    if s == t:   return ans
    for v, w in G[s]:
        if v == fa:   continue
        now_ans = dfs(v, s, t, ans * w)
        if now_ans > 0:  return now_ans
    return -1
n, q = map(int, input().split())
for i in range(n):
    va, sa, _, vb, sb = input().split()
    va, vb = float(va), float(vb)
    u, v = get_id(sa), get_id(sb)
    G[u].append((v, vb))
    G[v].append((u, 1.0 / vb))
for i in range(q):
    va, sa, _, sb = input().split()
    va = float(va)
    u, v = get_id(sa), get_id(sb)
    ans = dfs(u, -1, v, va)
    if ans > 0:  print(ans)  
    else:        print("impossible")

おすすめ

転載: blog.csdn.net/weixin_43914593/article/details/132492329