Skip to Content

Back and Forth

Análisis oficial (C++) 

Solución en video

Por Jonathan Paulson

Video de YouTube (yzPV0NZAUV4)

Código de la solución en video
#include <cassert> #include <cstdio> #include <iostream> #include <set> #include <vector> using namespace std; using ll = int64_t; // Las cantidades posibles que podrían quedar en el tanque del primer establo set<ll> possible; void solve(ll trips_left, const vector<ll> &buckets_here, const vector<ll> &buckets_there, ll tank_here, ll tank_there) { if (trips_left == 0) { // Completamos todos los viajes, así que la cantidad actual en el tanque del // primer establo es posible. Empezamos en el primer establo e hicimos cuatro // viajes, así que también terminamos en el primer establo, así que @tank_here representa // la cantidad en el tanque del primer establo possible.insert(tank_here); } else { for (ll taken_idx = 0; taken_idx < buckets_here.size(); taken_idx++) { ll bucket = buckets_here[taken_idx]; // Dejamos el balde tomado en el destino vector<ll> new_buckets_dest(buckets_there); new_buckets_dest.push_back(bucket); // Sacamos el balde tomado de nuestro establo actual vector<ll> new_buckets_src; for (ll i = 0; i < buckets_here.size(); i++) { if (i != taken_idx) { new_buckets_src.push_back(buckets_here[i]); } } // Movemos @bucket galones de leche del tanque actual al // otro tanque ll new_tank_dest = tank_there + bucket; ll new_tank_src = tank_here - bucket; // Como fuimos al otro establo, "here" ahora se refiere al establo // "dest" y "there" ahora se refiere al establo "src" solve(trips_left - 1, new_buckets_dest, new_buckets_src, new_tank_dest, new_tank_src); } } } int main() { assert(freopen("backforth.in", "r", stdin) != nullptr); assert(freopen("backforth.out", "w", stdout) != nullptr); vector<ll> buckets_here; for (ll i = 0; i < 10; i++) { ll bucket; cin >> bucket; buckets_here.push_back(bucket); } vector<ll> buckets_there; for (ll i = 0; i < 10; i++) { ll bucket; cin >> bucket; buckets_there.push_back(bucket); } solve(4, buckets_here, buckets_there, 1000, 1000); cout << possible.size() << endl; }
import java.io.*; import java.util.*; public class backforth { // Las cantidades posibles que podrían quedar en el tanque del primer establo static HashSet<Integer> possible = new HashSet<Integer>(); static void solve(int trips_left, ArrayList<Integer> buckets_here, ArrayList<Integer> buckets_there, int tank_here, int tank_there) { if (trips_left == 0) { // Completamos todos los viajes, así que la cantidad actual en el tanque // del primer establo es posible. Empezamos en el primer establo e // hicimos cuatro viajes, así que también terminamos en el primer establo, así que @tank_here // representa la cantidad en el tanque del primer establo possible.add(tank_here); } else { for (int taken_idx = 0; taken_idx < buckets_here.size(); taken_idx++) { int bucket = buckets_here.get(taken_idx); // Dejamos el balde tomado en el destino ArrayList<Integer> new_buckets_dest = new ArrayList<Integer>(buckets_there); new_buckets_dest.add(bucket); // Sacamos el balde tomado de nuestro establo actual ArrayList<Integer> new_buckets_src = new ArrayList<Integer>(); for (int i = 0; i < buckets_here.size(); i++) { if (i != taken_idx) { new_buckets_src.add(buckets_here.get(i)); } } // Movemos @bucket galones de leche del tanque actual al // otro tanque int new_tank_dest = tank_there + bucket; int new_tank_src = tank_here - bucket; // Como fuimos al otro establo, "here" ahora se refiere al // establo "dest" y "there" ahora se refiere al establo "src" solve(trips_left - 1, new_buckets_dest, new_buckets_src, new_tank_dest, new_tank_src); } } } public static void main(String[] args) throws Exception { BufferedReader in = new BufferedReader(new FileReader("backforth.in")); PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("backforth.out"))); String[] first_barn = in.readLine().split(" "); String[] second_barn = in.readLine().split(" "); ArrayList<Integer> buckets_here = new ArrayList<Integer>(); for (int i = 0; i < 10; i++) { buckets_here.add(Integer.parseInt(first_barn[i])); } ArrayList<Integer> buckets_there = new ArrayList<Integer>(); for (int i = 0; i < 10; i++) { buckets_there.add(Integer.parseInt(second_barn[i])); } solve(4, buckets_here, buckets_there, 1000, 1000); out.println(possible.size()); out.flush(); } }
# Las cantidades posibles que podrían quedar en el tanque del primer establo possible = set() def solve(trips_left, buckets_here, buckets_there, tank_here, tank_there): if trips_left == 0: # Completamos todos los viajes, así que la cantidad actual en el tanque del primer establo es posible # Empezamos en el primer establo e hicimos cuatro viajes, así que también terminamos en el primer establo, # así que @tank_here representa la cantidad en el tanque del primer establo possible.add(tank_here) else: for taken_idx, bucket in enumerate(buckets_here): # Dejamos el balde tomado en el destino new_buckets_dest = buckets_there + [bucket] # Sacamos el balde tomado de nuestro establo actual new_buckets_src = [b for i, b in enumerate(buckets_here) if i != taken_idx] # Movemos @bucket galones de leche del tanque actual al otro tanque new_tank_dest = tank_there + bucket new_tank_src = tank_here - bucket # Como fuimos al otro establo, "here" ahora se refiere al establo "dest" y # "there" ahora se refiere al establo "src" solve( trips_left - 1, new_buckets_dest, new_buckets_src, new_tank_dest, new_tank_src, ) first_barn, second_barn = open("backforth.in").readlines() buckets_here = [int(x) for x in first_barn.split()] buckets_there = [int(x) for x in second_barn.split()] # Terminamos haciendo 4 viajes de ida y vuelta # Cada tanque empieza con 1000 galones de leche # Es imposible quedarse sin leche en alguno de los tanques, # ya que solo hacemos 4 viajes y cada balde guarda como máximo 100 galones solve(4, buckets_here, buckets_there, 1000, 1000) with open("backforth.out", "w") as fout: print(len(possible), file=fout)
Pista 1

¿Qué información necesitamos cuando Farmer John llega a un establo?

Respuesta a la Pista 1

Hay que conocer el día, los baldes disponibles en cada establo y las cantidades actuales de los tanques.

Pista 2

En cada momento, podríamos elegir cualquier balde para mover. ¿Podríamos escribir una lógica general para manejar todos estos estados posibles?

Solución

Solución

Similar a la segunda solución del análisis.

#include <bits/stdc++.h> using namespace std; set<int> possible; void get_possible(int day, int a_tank, vector<int> a_buckets, int b_tank, vector<int> b_buckets) { // Último día, agregamos la cantidad de leche del primer tanque. if (day == 4) { possible.insert(a_tank); return; } // Esto transfiere cada balde posible del establo x al establo y. for (int i = 0; i < a_buckets.size(); i++) { // Balde a transferir. int t = a_buckets[i]; // Creamos una copia nueva de los baldes disponibles y transferimos el i-ésimo. vector<int> new_a = a_buckets; new_a.erase(begin(new_a) + i); vector<int> new_b = b_buckets; new_b.push_back(t); // Llamamos recursivamente a la función con los nuevos baldes y cantidades de tanque. get_possible(day + 1, b_tank + t, new_b, a_tank - t, new_a); } } int main() { freopen("backforth.in", "r", stdin); freopen("backforth.out", "w", stdout); vector<int> a(10); for (int &i : a) { cin >> i; } vector<int> b(10); for (int &i : b) { cin >> i; } get_possible(0, 1000, a, 1000, b); cout << possible.size() << endl; }
import java.io.*; import java.util.*; public class BackForth { static Set<Integer> possible = new HashSet<>(); public static void main(String[] args) throws IOException { BufferedReader read = new BufferedReader(new FileReader("backforth.in")); StringTokenizer aST = new StringTokenizer(read.readLine()); StringTokenizer bST = new StringTokenizer(read.readLine()); List<Integer> a = new ArrayList<>(); List<Integer> b = new ArrayList<>(); for (int i = 0; i < 10; i++) { a.add(Integer.parseInt(aST.nextToken())); b.add(Integer.parseInt(bST.nextToken())); } getPossible(0, 1000, a, 1000, b); PrintWriter write = new PrintWriter("backforth.out"); write.println(possible.size()); write.close(); } static void getPossible(int day, int aTank, List<Integer> aBuckets, int bTank, List<Integer> bBuckets) { // Último día, agregamos la cantidad de leche del primer tanque. if (day == 4) { possible.add(aTank); return; } // Esto transfiere cada balde posible del establo x al establo y. for (int i = 0; i < aBuckets.size(); i++) { // Balde a transferir. int t = aBuckets.get(i); // Creamos una copia nueva de los baldes disponibles y transferimos el // i-ésimo. List<Integer> newA = new ArrayList<>(aBuckets); newA.remove(i); List<Integer> newB = new ArrayList<>(bBuckets); newB.add(t); // Llamamos recursivamente a la función con los nuevos baldes y // cantidades de tanque. getPossible(day + 1, bTank + t, newB, aTank - t, newA); } } }
import sys from typing import List sys.stdin = open("backforth.in", "r") sys.stdout = open("backforth.out", "w") possible = set() def get_possible( day: int, a_tank: int, a_buckets: List[int], b_tank: int, b_buckets: List[int] ) -> None: # Último día, agregamos la cantidad de leche del primer tanque. if day == 4: possible.add(a_tank) return # Esto transfiere cada balde posible del establo x al establo y. for i in range(len(a_buckets)): # Balde a transferir. t = a_buckets[i] # Creamos una copia nueva de los baldes disponibles y transferimos el i-ésimo. new_a = a_buckets.copy() del new_a[i] new_b = b_buckets.copy() new_b.append(t) # Llamamos recursivamente a la función con los nuevos baldes y cantidades de tanque. get_possible(day + 1, b_tank + t, new_b, a_tank - t, new_a) a = list(map(int, input().split())) b = list(map(int, input().split())) get_possible(0, 1000, a, 1000, b) print(len(possible))