Verificar todo - Scala
Puntaje estimado: 2m ^ n
Comienzo desde cada máquina e itero sobre todas las tareas para crear todas las permutaciones a través de las tareas con diferentes máquinas que cumplen con los plazos. Es decir, si todo está a tiempo, obtendría 9 rutas posibles con 2 máquinas y 3 tareas. (m ^ n) Luego, tomo el camino con el costo más bajo.
La entrada está estructurada de esta manera (-> explica las partes y, por lo tanto, no debe ingresarse):
M_1:5 3 5 4;M_2:4 2 7 5 --> time
M_1:5 4 2 6;M_2:3 7 3 3 --> cost
M_1:M_1}0 M_2}1;M_2:M_1}2 M_2}0 --> switch itme
M_1:M_1}0 M_2}2;M_2:M_1}1 M_2}0 --> switch cost
5 10 15 20 --> deadlines
Y aquí está el código:
package Scheduling
import scala.io.StdIn.readLine
case class Cost(task: Map[String, List[Int]])
case class Switch(machine: Map[String, Map[String, Int]])
case class Path(time: Int, cost: Int, machine: List[String])
object Main {
def main(args: Array[String]) {
val (machines, cost_time, cost_money, switch_time, switch_money, deadlines) = getInput
val s = new Scheduler(machines, cost_time, cost_money, switch_time, switch_money, deadlines)
s.schedule
}
def getInput(): (List[String], Cost, Cost, Switch, Switch, List[Int]) = {
val cost_time = Cost(readLine("time to complete task").split(";").map{s =>
val parts = s.split(":")
(parts(0) -> parts(1).split(" ").map(_.toInt).toList)
}.toMap)
val cost_money = Cost(readLine("cost to complete task").split(";").map{s =>
val parts = s.split(":")
(parts(0) -> parts(1).split(" ").map(_.toInt).toList)
}.toMap)
val switch_time = Switch(readLine("time to switch").split(";").map{s =>
val parts = s.split(":")
(parts(0) -> parts(1).split(" ").map{t =>
val entries = t.split("}")
(entries(0) -> entries(1).toInt)
}.toMap)
}.toMap)
val switch_money = Switch(readLine("time to switch").split(";").map{s =>
val parts = s.split(":")
(parts(0) -> parts(1).split(" ").map{t =>
val entries = t.split("}")
(entries(0) -> entries(1).toInt)
}.toMap)
}.toMap)
val deadlines = readLine("deadlines").split(" ").map(_.toInt).toList
val machines = cost_time.task.keys.toList
(machines, cost_time, cost_money, switch_time, switch_money, deadlines)
}
}
class Scheduler(machines: List[String], cost_time: Cost, cost_money: Cost, switch_time: Switch, switch_money: Switch, deadlines: List[Int]) {
def schedule() {
var paths = List[Path]()
var alternatives = List[(Int, Path)]()
for (i <- machines) {
if (cost_time.task(i)(0) <= deadlines(0)) {
paths = paths ::: List(Path(cost_time.task(i)(0), cost_money.task(i)(0), List(i)))
}
}
val allPaths = deadlines.zipWithIndex.tail.foldLeft(paths)((paths, b) => paths.flatMap(x => calculatePath(x, b._1, b._2)))
if (allPaths.isEmpty) {
println("It is not possible")
} else {
println(allPaths.minBy(p=>p.cost).machine)
}
}
def calculatePath(prev: Path, deadline: Int, task: Int): List[Path] = {
val paths = machines.map(m => calculatePath(prev, task, m))
paths.filter(p => p.time <= deadline)
}
def calculatePath(prev: Path, task: Int, machine: String): Path = {
val time = prev.time + switch_time.machine(prev.machine.last)(machine) + cost_time.task(machine)(task)
val cost = prev.cost + switch_money.machine(prev.machine.last)(machine) + cost_money.task(machine)(task)
Path(time, cost, prev.machine :+ machine)
}
}
También tuve una idea para comenzar desde atrás. Dado que siempre puede elegir una máquina con el costo más bajo si el tiempo es menor, entonces la diferencia de la fecha límite anterior a la nueva. Pero eso no disminuiría el tiempo de ejecución máximo si la tarea con el mejor costo toma más tiempo que la última fecha límite.
Actualizar
======
Aquí hay otra configuración. hora:
M_1 2 2 2 7
M_2 1 8 5 10
costo:
M_1 4 4 4 4
M_2 1 1 1 1
tiempo de cambio:
M_1 M_2
M_1 0 2
M_2 6 0
costo de cambio:
M_1 M_2
M_1 0 2
M_2 2 0
plazos de entrega:
5 10 15 20
Como entrada en mi programa:
M_1:2 2 2 7;M_2:1 8 5 10
M_1:4 4 4 4;M_2:1 1 1 1
M_1:M_1}0 M_2}2;M_2:M_1}6 M_2}0
M_1:M_1}0 M_2}2;M_2:M_1}2 M_2}0
5 10 15 20
Este tiene dos soluciones: tiempo: 18, costo: 15, ruta: Lista (M_1, M_1, M_1, M_2) tiempo: 18, costo: 15, ruta: Lista (M_2, M_1, M_1, M_1)
Lo que plantea la pregunta de cómo se debe manejar esto. ¿Se deben imprimir todos o solo uno? ¿Y si el tiempo fuera diferente? ¿Es uno con el costo más bajo y no tiene una fecha límite perdida suficiente o también debería ser el que tiene el tiempo más bajo?