Rest Stops
Solución en video
Por Vivian Han
Video de YouTube (gyg047C-754)
Código de la solución en video
// #define reststops 1;
// #ifdef reststops
#include <fstream>
#include <iostream>
using namespace std;
int32_t trailLen, stopNum, fRate, bRate;
int32_t x[100000];
int32_t c[100000];
bool good[100000];
int main() {
ifstream in;
in.open("reststops.in");
in >> trailLen >> stopNum >> fRate >> bRate;
// leemos los datos de las paradas
for (int i = 0; i < stopNum; i++) { in >> x[i] >> c[i]; }
// hallamos todas las paradas "mejores"
int32_t max = 0;
for (int i = stopNum - 1; i >= 0; i--) {
good[i] = false;
if (c[i] > max) { // no hay paradas después de i que sean "mejores"
good[i] = true;
max = c[i];
}
}
// simulamos todo el sendero
long long prevStopPos = 0;
long long ans = 0;
for (int i = 0; i < stopNum; i++) {
if (good[i]) {
long long travelDist = x[i] - prevStopPos;
long long fTime = travelDist * fRate;
long long bTime = travelDist * bRate;
long long restTime = fTime - bTime;
ans += restTime * c[i];
prevStopPos = x[i];
}
}
// */
ofstream out;
out.open("reststops.out");
out << ans << endl;
out.close();
// cout << ans << endl;
return 0;
}
// #endifimport java.io.*;
public class RestStops {
static int[] x, c;
static boolean[] good;
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(new FileReader("reststops.in"));
String[] line = br.readLine().split(" ");
int trailLen = Integer.parseInt(line[0]); // este valor nunca se usa...
int stopNum = Integer.parseInt(line[1]);
int fRate = Integer.parseInt(line[2]);
int bRate = Integer.parseInt(line[3]);
x = new int[stopNum];
c = new int[stopNum];
good = new boolean[stopNum];
// leemos los datos de las paradas
for (int i = 0; i < stopNum; i++) {
line = br.readLine().split(" ");
x[i] = Integer.parseInt(line[0]);
c[i] = Integer.parseInt(line[1]);
}
br.close();
// hallamos todas las paradas "mejores"
int max = 0;
for (int i = stopNum - 1; i >= 0; i--) {
if (c[i] > max) { // no hay paradas después de i que sean "mejores"
good[i] = true;
max = c[i];
}
}
// simulamos todo el sendero
int prevStopPos = 0;
long ans = 0;
for (int i = 0; i < stopNum; i++) {
if (good[i]) {
long travelDist = x[i] - prevStopPos;
long fTime = travelDist * fRate;
long bTime = travelDist * bRate;
long restTime = fTime - bTime;
ans += restTime * c[i];
prevStopPos = x[i];
}
}
BufferedWriter bw = new BufferedWriter(new FileWriter("reststops.out"));
bw.write(ans + "\n");
bw.close();
} catch (Exception e) { System.out.println(e.getMessage()); }
}
}Explicación
Supongamos que temprano en la caminata hay una parada con sabor , pero más adelante hay una parada con sabor donde . Entonces, nunca es óptimo que Bessie pase tiempo en la primera parada con sabor . Si lo hiciera, podría pasar la misma cantidad de tiempo en la parada posterior y ganar más unidades de sabor; igual nunca quedaría detrás de Farmer John. Así, las únicas paradas en las que Bessie podría detenerse son las que tienen más sabor que cualquier parada posterior.
Podemos hallar estas paradas “maximalmente a la derecha” en un solo barrido de derecha a izquierda (o de fin a inicio), llevando la cuenta del mayor sabor visto hasta ahora. Si la parada actual supera el mayor valor visto hasta ahora, es “maximalmente a la derecha”.
Ahora podemos aplicar un algoritmo voraz: nunca parar en paradas que no sean maximalmente a la derecha. Bessie debería detenerse en una parada maximalmente a la derecha el mayor tiempo posible (es decir, hasta que Farmer John la alcance). Luego sigue hasta la siguiente parada maximalmente a la derecha.
Para ver la corrección de este algoritmo voraz, supongamos que Bessie no pasó tanto tiempo como podía en alguna parada maximalmente a la derecha . Entonces dejaría esta parada segundos antes, para algún positivo. Supongamos que el siguiente lugar en el que Bessie se detiene es la parada . Podríamos mejorar la ingesta de sabor de Bessie haciendo que pase segundo menos en y segundo más en la parada . Se puede verificar que Bessie igual nunca quedaría detrás de Farmer John, y como el sabor en es mayor que el sabor en , mejoramos el resultado de Bessie. Por lo tanto ninguna solución óptima deja una parada maximalmente a la derecha antes de tiempo, y nuestro algoritmo voraz es correcto.
Implementación
Complejidad temporal:
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
int main() {
ifstream in("reststops.in");
int trail_len; // no se usa
int stop_num;
int f_rate;
int b_rate;
in >> trail_len >> stop_num >> f_rate >> b_rate;
vector<int> x(stop_num); // posición de cada parada
vector<int> c(stop_num); // valor de sabor de cada parada
for (int i = 0; i < stop_num; i++) { in >> x[i] >> c[i]; }
// hallamos todas las paradas "mejores"
vector<bool> good(stop_num);
int max_tastiness = 0;
for (int i = stop_num - 1; i >= 0; i--) {
if (c[i] > max_tastiness) {
// no hay paradas después de i que sean "mejores"
good[i] = true;
max_tastiness = c[i];
}
}
int total = 0;
for (bool i : good) total += i;
cout << total << endl;
// simulamos todo el sendero
long long prev_stop_pos = 0;
long long ans = 0;
for (int i = 0; i < stop_num; i++) {
if (good[i]) {
long long travel_dist = x[i] - prev_stop_pos;
long long f_time = travel_dist * f_rate;
long long b_time = travel_dist * b_rate;
long long rest_time = f_time - b_time;
ans += rest_time * c[i];
prev_stop_pos = x[i];
}
}
ofstream("reststops.out") << ans << endl;
}import java.io.*;
public class RestStops {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("reststops.in"));
String[] line = br.readLine().split(" ");
int trailLen = Integer.parseInt(line[0]); // nunca se usa
int stopNum = Integer.parseInt(line[1]);
int fRate = Integer.parseInt(line[2]);
int bRate = Integer.parseInt(line[3]);
int[] x = new int[stopNum]; // posición de cada parada
int[] c = new int[stopNum]; // valor de sabor de cada parada
for (int i = 0; i < stopNum; i++) {
line = br.readLine().split(" ");
x[i] = Integer.parseInt(line[0]);
c[i] = Integer.parseInt(line[1]);
}
br.close();
// hallamos todas las paradas "mejores"
boolean[] good = new boolean[stopNum];
int maxTastiness = 0;
for (int i = stopNum - 1; i >= 0; i--) {
if (c[i] > maxTastiness) {
// no hay paradas después de i que sean "mejores"
good[i] = true;
maxTastiness = c[i];
}
}
// simulamos todo el sendero
int prevStopPos = 0;
long ans = 0;
for (int i = 0; i < stopNum; i++) {
if (good[i]) {
long travelDist = x[i] - prevStopPos;
long fTime = travelDist * fRate;
long bTime = travelDist * bRate;
long restTime = fTime - bTime;
ans += restTime * c[i];
prevStopPos = x[i];
}
}
PrintWriter pw = new PrintWriter("reststops.out");
pw.println(ans);
pw.close();
}
}with open("reststops.in") as read:
# trail_len no se usa
trail_len, stop_num, f_rate, b_rate = [int(i) for i in read.readline().split()]
x = [] # posición de cada parada
c = [] # valor de sabor de cada parada
for _ in range(stop_num):
a, b = [int(i) for i in read.readline().split()]
x.append(a)
c.append(b)
# hallamos todas las paradas "mejores"
good = [False for _ in range(stop_num)]
max_tastiness = 0
for i in range(stop_num - 1, -1, -1):
if c[i] > max_tastiness:
# no hay paradas después de i que sean "mejores"
good[i] = True
max_tastiness = c[i]
# simulamos todo el sendero
prev_stop_pos = 0
ans = 0
for i in range(stop_num):
if good[i]:
travel_dist = x[i] - prev_stop_pos
f_time = travel_dist * f_rate
b_time = travel_dist * b_rate
rest_time = f_time - b_time
ans += rest_time * c[i]
prev_stop_pos = x[i]
print(ans, file=open("reststops.out", "w"))