Головоломка с двумя кувшинами для воды
Вы на берегу реки. Вам дается m- литровый кувшин и n- литровый кувшин, где 0 <m <n . Оба кувшина изначально пусты. На кувшинах нет маркировки, позволяющей отмерять меньшее количество. Вы должны использовать кувшины для измерения d литров воды, где d <n. Определите минимальное количество операций, которые необходимо выполнить для получения d литров воды в одной из кувшинов.
Вы можете выполнять следующие операции:
- Опустошить кувшин
- Наполнить кувшин
- Налейте воду из одного кувшина в другой, пока один из кувшинов не станет пустым или полным.
Есть несколько способов решения этой проблемы, включая BFS и DP. В этой статье обсуждается арифметический подход к решению задачи. Задачу можно смоделировать с помощью диофантова уравнения вида mx + ny = d, которое разрешимо тогда и только тогда, когда gcd (m, n) делит d. Кроме того, решение x, y, для которого выполняется уравнение, может быть получено с использованием расширенного алгоритма Евклида для GCD.
Например, если у нас есть кувшин J1 на 5 литров (n = 5) и другой кувшин J2 на 3 литра (m = 3), и мы должны отмерить 1 литр воды, используя их. Соответствующее уравнение будет 5n + 3m = 1. Прежде всего, эта проблема может быть решена, так как gcd (3,5) = 1, который делит 1 (см. Это для подробного объяснения). Используя расширенный алгоритм Евклида, мы получаем значения n и m, для которых выполняется уравнение: n = 2 и m = -3. Эти значения n, m также имеют некоторое значение, например, здесь n = 2 и m = -3 означает, что мы должны заполнить J1 дважды и пустить J2 трижды.
Теперь, чтобы найти минимальное количество операций, которые необходимо выполнить, нам нужно решить, какой кувшин следует наполнить в первую очередь. В зависимости от того, какой кувшин выбран для наполнения, а какой - опорожниться, у нас есть два разных решения, и наш ответ будет минимальным из них.
Раствор 1 (всегда переливайте из m-литрового кувшина в n-литровый кувшин)
- Наполните m-литровый кувшин и вылейте его в n-литровый кувшин.
- Когда кувшин станет пустым, наполните его.
- Когда n-литровый кувшин становится полным, он опустошается.
- Повторите шаги 1,2,3 до тех пор, пока в кувшине объемом n литров или кувшине m литров не будет d литров воды.
Каждый из шагов 1, 2 и 3 считается как одна выполняемая нами операция. Допустим, алгоритм 1 решает задачу за количество операций C1.
Раствор 2 (всегда переливайте из n-литрового кувшина в m-литровый кувшин)
- Наполните кувшин емкостью n литров и вылейте его в кувшин емкостью m литров.
- Когда кувшин объемом n литров станет пустым, наполните его.
- Когда кувшин объемом m литров становится полным, он опустошается.
- Повторяйте шаги 1, 2 и 3 до тех пор, пока в кувшине объемом n литров или кувшине m литров не будет d литров воды.
Допустим, решение 2 решает задачу в C2, количество операций.
Теперь наше окончательное решение будет состоять минимум из C1 и C2.
Теперь проиллюстрируем, как работают оба решения. Предположим, что есть кувшин на 3 литра и кувшин на 5 литров для измерения 4 литров воды, поэтому m = 3, n = 5 и d = 4 . Соответствующее диофантово уравнение будет 3m + 5n = 4. Мы используем пары (x, y) для представления количества воды внутри 3-литрового и 5-литрового кувшина соответственно на каждом этапе разлива.
При использовании Решения 1 последовательные этапы заливки:
(0,0) -> (3,0) -> (0,3) -> (3,3) -> (1,5) -> (1,0) -> (0,1) -> ( 3,1) -> (0,4)
Следовательно, вам нужно выполнить 8 операций.
При использовании Решения 2 последовательные этапы заливки:
(0,0) -> (0,5) -> (3,2) -> (0,2) -> (2,0) -> (2,5) -> (3,4)
Следовательно, вам нужно выполнить 6 операций.
Следовательно, мы использовали бы раствор 2, чтобы отмерить 4 литра воды за 6 операций или ходов.
Based on the explanation here is the implementation.
C++
// C++ program to count minimum number of steps // required to measure d litres water using jugs // of m liters and n liters capacity. #include <bits/stdc++.h> using namespace std; // Utility function to return GCD of "a" // and "b". int gcd( int a, int b) { if (b==0) return a; return gcd(b, a%b); } /* fromCap -- Capacity of jug from which water is poured toCap -- Capacity of jug to which water is poured d -- Amount to be measured */ int pour( int fromCap, int toCap, int d) { // Initialize current amount of water // in source and destination jugs int from = fromCap; int to = 0; // Initialize count of steps required int step = 1; // Needed to fill "from" Jug // Break the loop when either of the two // jugs has d litre water while (from != d && to != d) { // Find the maximum amount that can be // poured int temp = min(from, toCap - to); // Pour "temp" liters from "from" to "to" to += temp; from -= temp; // Increment count of steps step++; if (from == d || to == d) break ; // If first jug becomes empty, fill it if (from == 0) { from = fromCap; step++; } // If second jug becomes full, empty it if (to == toCap) { to = 0; step++; } } return step; } // Returns count of minimum steps needed to // measure d liter int minSteps( int m, int n, int d) { // To make sure that m is smaller than n if (m > n) swap(m, n); // For d > n we cant measure the water // using the jugs if (d > n) return -1; // If gcd of n and m does not divide d // then solution is not possible if ((d % gcd(n,m)) != 0) return -1; // Return minimum two cases: // a) Water of n liter jug is poured into // m liter jug // b) Vice versa of "a" return min(pour(n,m,d), // n to m pour(m,n,d)); // m to n } // Driver code to test above int main() { int n = 3, m = 5, d = 4; printf ( "Minimum number of steps required is %d" , minSteps(m, n, d)); return 0; } |
Java
// Java program to count minimum number of // steps required to measure d litres water // using jugs of m liters and n liters capacity. import java.io.*; class GFG{ // Utility function to return GCD of "a" // and "b". public static int gcd( int a, int b) { if (b == 0 ) return a; return gcd(b, a % b); } /* fromCap -- Capacity of jug from which water is poured toCap -- Capacity of jug to which water is poured d -- Amount to be measured */ public static int pour( int fromCap, int toCap, int d) { // Initialize current amount of water // in source and destination jugs int from = fromCap; int to = 0 ; // Initialize count of steps required int step = 1 ; // Needed to fill "from" Jug // Break the loop when either of the two // jugs has d litre water while (from != d && to != d) { // Find the maximum amount that can be // poured int temp = Math.min(from, toCap - to); // Pour "temp" liters from "from" to "to" to += temp; from -= temp; // Increment count of steps step++; if (from == d || to == d) break ; // If first jug becomes empty, fill it if (from == 0 ) { from = fromCap; step++; } // If second jug becomes full, empty it if (to == toCap) { to = 0 ; step++; } } return step; } // Returns count of minimum steps needed to // measure d liter public static int minSteps( int m, int n, int d) { // To make sure that m is smaller than n if (m > n) { int t = m; m = n; n = t; } // For d > n we cant measure the water // using the jugs if (d > n) return - 1 ; // If gcd of n and m does not divide d // then solution is not possible if ((d % gcd(n, m)) != 0 ) return - 1 ; // Return minimum two cases: // a) Water of n liter jug is poured into // m liter jug // b) Vice versa of "a" return Math.min(pour(n, m, d), // n to m pour(m, n, d)); // m to n } // Driver code public static void main(String[] args) { int n = 3 , m = 5 , d = 4 ; System.out.println( "Minimum number of " + "steps required is " + minSteps(m, n, d)); } } // This code is contributed by RohitOberoi |
Python3
# Python3 implementation of program to count # minimum number of steps required to measure # d litre water using jugs of m liters and n # liters capacity. def gcd(a, b): if b = = 0 : return a return gcd(b, a % b) """ fromCap -- Capacity of jug from which water is poured toCap -- Capacity of jug to which water is poured d -- Amount to be measured """ def Pour(toJugCap, fromJugCap, d): # Initialize current amount of water # in source and destination jugs fromJug = fromJugCap toJug = 0 # Initialize steps required step = 1 while ((fromJug is not d) and (toJug is not d)): # Find the maximum amount that can be # poured temp = min (fromJug, toJugCap - toJug) # Pour "temp" liter from "fromJug" to "toJug" toJug = toJug + temp fromJug = fromJug - temp step = step + 1 if ((fromJug = = d) or (toJug = = d)): break # If first jug becomes empty, fill it if fromJug = = 0 : fromJug = fromJugCap step = step + 1 # If second jug becomes full, empty it if toJug = = toJugCap: toJug = 0 step = step + 1 return step # Returns count of minimum steps needed to # measure d liter def minSteps(n, m, d): if m> n: temp = m m = n n = temp if (d % (gcd(n,m)) is not 0 ): return - 1 # Return minimum two cases: # a) Water of n liter jug is poured into # m liter jug return ( min (Pour(n,m,d), Pour(m,n,d))) # Driver code if __name__ = = "__main__" : n = 3 m = 5 d = 4 print ( "Minimum number of steps required is" , minSteps(n, m, d)) # This code is contributed by Sanket Badhe |
Javascript
<script> // Javascript program to count minimum number of // steps required to measure d litres water // using jugs of m liters and n liters capacity. // Utility function to return GCD of "a" // and "b". function gcd(a , b) { if (b == 0) return a; return gcd(b, a % b); } /* fromCap -- Capacity of jug from which water is poured toCap -- Capacity of jug to which water is poured d -- Amount to be measured */ function pour(fromCap , toCap , d) { // Initialize current amount of water // in source and destination jugs var from = fromCap; var to = 0; // Initialize count of steps required var step = 1; // Needed to fill "from" Jug // Break the loop when either of the two // jugs has d litre water while (from != d && to != d) { // Find the maximum amount that can be // poured var temp = Math.min(from, toCap - to); // Pour "temp" liters from "from" to "to" to += temp; from -= temp; // Increment count of steps step++; if (from == d || to == d) break ; // If first jug becomes empty, fill it if (from == 0) { from = fromCap; step++; } // If second jug becomes full, empty it if (to == toCap) { to = 0; step++; } } return step; } // Returns count of minimum steps needed to // measure d liter function minSteps(m , n , d) { &
РЕКОМЕНДУЕМЫЕ СТАТЬИ |