Cod sursa(job #2943182)

Utilizator lucian.stefanoaicaLucian S lucian.stefanoaica Data 20 noiembrie 2022 18:00:53
Problema Ubuntzei Scor 0
Compilator java Status done
Runda Arhiva de probleme Marime 6.27 kb
package com.hometech.ubuntzei;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class Main {

    private Distances distances;

    public static void main(String[] args) {
        Main app = new Main();
        app.run();
    }

    public void run() {
        try {
            File file = new File("ubuntzei.in");
            Scanner scanner = new Scanner(file);
            scanner.useDelimiter("\n");

            List<String> lines = new ArrayList<>();

            while (scanner.hasNext()) {
                lines.add(scanner.next());
            }

            scanner.close();

            String firstLine = lines.get(0);
            String secondLine = lines.get(1);

            int numberOfNodes = Integer.valueOf(firstLine.split(" ")[0]);
            int numberOfLinks = Integer.valueOf(firstLine.split(" ")[1]);

            String[] wordsFromSecondLine = secondLine.split(" ");
            List<Integer> nodesToVisitIds = new ArrayList<>();
            int numberOfNodesToVisit = Integer.valueOf(wordsFromSecondLine[0]);

            for (int i = 1; i <= numberOfNodesToVisit; ++i) {
                nodesToVisitIds.add(Integer.valueOf(wordsFromSecondLine[i]));
            }

            Map<Integer, Node> nodes = new HashMap<Integer, Node>();
            for (int i = 1; i <= numberOfNodes; ++i) {
                Node node = new Node(i);
                nodes.put(i, node);
            }

            distances = new Distances(numberOfLinks);

            for (int lineNumber = 2; lineNumber < numberOfLinks + 2; ++lineNumber) {
                String line = lines.get(lineNumber);
                String[] words = line.split(" ");
                Integer firstNodeId = Integer.valueOf(words[0]);
                Integer secondNodeId = Integer.valueOf(words[1]);
                Integer cost = Integer.valueOf(words[2]);
                distances.addDistance(firstNodeId, secondNodeId, cost);
                Node firstNode = nodes.get(firstNodeId);
                Node secondNode = nodes.get(secondNodeId);
                firstNode.addLink(secondNode);
                secondNode.addLink(firstNode);
            }

            Node start = nodes.get(1);
            Node finish = nodes.get(numberOfNodes);
            long minimumCost = Integer.MAX_VALUE;

            List<Node> nodesToVisit = new ArrayList<>();
            for (Integer id : nodesToVisitIds) {
                nodesToVisit.add(nodes.get(id));
            }

            long finalMinimumCost = 0;

            while (nodesToVisit.isEmpty() == false) {
                Node choosenNode = nodesToVisit.get(0);
                for (Node node : nodesToVisit) {
                    long temp = computeMinimumCost(start, node);
                    if (temp < minimumCost) {
                        minimumCost = temp;
                        choosenNode = node;
                    }
                }
                start = choosenNode;
                nodesToVisit.remove(choosenNode);
                finalMinimumCost += minimumCost;
            }

            finalMinimumCost += computeMinimumCost(start, finish);
            Writer write = new FileWriter("ubuntzei.out");
            write.write(String.valueOf(finalMinimumCost));

            write.close();

        } catch (IOException e) {
            System.err.println(e);
        }
    }

    private long computeMinimumCost(Node first, Node last) {
        return computeMinimumCostRecursively(first, new ArrayList<>(), last);
    }

    private long computeMinimumCostRecursively(Node currentNode, List<Node> previousNodes, Node targetNode) {
        if (currentNode.getId() == targetNode.getId()) {
            return 0;
        }

        long minimumCost = Integer.MAX_VALUE;
        for (Node link : currentNode.getLinks()) {

            if (contains(previousNodes, link) == false) {
                previousNodes.add(currentNode);
                long cost = distances.getDistance(currentNode, link) +
                        computeMinimumCostRecursively(link, previousNodes, targetNode);
                previousNodes.remove(currentNode);
                if (cost < minimumCost) {
                    minimumCost = cost;
                }
            }
        }
        return minimumCost;
    }

    private boolean contains(List<Node> nodes, Node nodeToSearchFor) {
        boolean result = false;
        for (Node node : nodes) {
            if (node.getId() == nodeToSearchFor.getId()) {
                result = true;
                break;
            }
        }
        return result;
    }
}

class Distances {

    private int size;
    private int[][] matrix;

    public Distances(int size) {
        this.size = size;
        this.matrix = new int[size][size];
    }

    public void addDistance(Integer firstNodeId, Integer secondNodeId, Integer cost) {
        matrix[firstNodeId][secondNodeId] = cost;
        matrix[secondNodeId][firstNodeId] = cost;
    }

    public Integer getDistance(Node first, Node second) {
        int firstNodeId = first.getId();
        int secondNodeId = second.getId();
        return matrix[firstNodeId][secondNodeId];
    }

    public void print() {
        for (int i = 1; i < size; ++i) {
            for (int j = 1; j < size; ++j) {
                System.out.print(matrix[i][j]);
            }
            System.out.println("");
        }
    }
}

class Node {

    private int id;
    private List<Node> links = new ArrayList<>();

    public Node(int id) {
        this.id = id;
    }

    public void addLink(Node node) {
        this.links.add(node);
    }

    @Override
    public String toString() {
        StringBuilder linkIds = new StringBuilder();
        for (Node node : links) {
            linkIds.append(node.getId() + " ");
        }
        return "( id: " + id + " links: " + linkIds + ")";
    }

    public int getId() {
        return id;
    }

    public boolean hasDirectLinkWith(Node targetNode) {
        boolean result = false;
        for (Node node : links) {
            if (node.getId() == targetNode.getId()) {
                result = true;
                break;
            }
        }
        return result;
    }

    public List<Node> getLinks() {
        return links;
    }
}