Count ways to traverse all N cities when each city is traversed K times
For N given cities, find how many ways a driver can traverse through them so that each town is visited exactly K times. From each city he can go to every other city (except the city which is already in it).
Example:
Input: N = 3, K = 1
Output: 6
Explanation: The possible paths are
1 -> 2 -> 3
1 -> 3 -> 2
2 -> 1 -> 3
2 -> 3 -> 1
3 -> 1 -> 2
3 -> 2 -> 1Input: N = 3, K = 2
Output: 30
Explanation: The possible paths are
1 -> 2 -> 1 -> 3 -> 2 -> 3, 1 -> 2 -> 3 -> 1 -> 2 -> 3
1 -> 2 -> 3 -> 1 -> 3 -> 2, 1 -> 2 -> 3 -> 2 -> 1 -> 3
1 -> 2 -> 3 -> 2 -> 3 -> 1, 1 -> 3 -> 1 -> 2 -> 3 -> 2
1 -> 3 -> 2 -> 1 -> 2 -> 3, 1 -> 3 -> 2 -> 1 -> 3 -> 2
1 -> 3 -> 2 -> 3 -> 1 -> 2, 1 -> 3 -> 2 -> 3 -> 2 -> 1
2 -> 1 -> 2 -> 3 -> 1 -> 3, 2 -> 1 -> 3 -> 1 -> 2 -> 3
2 -> 1 -> 3 -> 1 -> 3 -> 2, 2 -> 1 -> 3 -> 2 -> 1 -> 3
2 -> 1 -> 3 -> 2 -> 3 -> 1, 2 -> 3 -> 1 -> 2 -> 1 -> 3
2 -> 3 -> 1 -> 2 -> 3 -> 1, 2 -> 3 -> 1 -> 3 -> 1 -> 2
2 -> 3 -> 1 -> 3 -> 2 -> 1, 2 -> 3 -> 2 -> 1 -> 3 -> 1
3 -> 1 -> 2 -> 1 -> 2 -> 3, 3 -> 1 -> 2 -> 1 -> 3 -> 2
3 -> 1 -> 2 -> 3 -> 1 -> 2, 3 -> 1 -> 2 -> 3 -> 2 -> 1
3 -> 1 -> 3 -> 2 -> 1 -> 2, 3 -> 2 -> 1 -> 2 -> 1 -> 3
3 -> 2 -> 1 -> 2 -> 3 -> 1, 3 -> 2 -> 1 -> 3 -> 1 -> 2
3 -> 2 -> 1 -> 3 -> 2 -> 1, 3 -> 2 -> 3 -> 1 -> 2 -> 1
Naive solution
The naive approach is to generate all the combinations and increment a counter for every possible arrangement that doesn’t have two same adjacent elements.
Below is the implementation of the above approach:
C++
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std; // Function to find the number of possible paths ulong driversProblem( int n, int k) { ulong num_of_paths = 0; vector< int > path; // Filling the vector with the first path for ( int i = 1; i <= n; i++) { for ( int j = 0; j < k; j++) { path.push_back(i); } } bool valid_path; while (next_permutation(path.begin(), path.end())) { valid_path = true ; // Checking if there is 2 adjacent cities // in the path for ( int i = 0; i < n * k - 1; i++) { if (path[i] == path[i + 1]) { valid_path = false ; } } // Incrementing the counter if // the path generated is valid if (valid_path == true ) { num_of_paths++; } } return num_of_paths; } // Driver code int main() { int N = 3, K = 2; // Function call cout << driversProblem(N, K) << endl; return 0; } |
Java
/*package whatever //do not write package name here */ import java.io.*; class GFG { // Function to find the number of possible paths static long driversProblem( int n, int k) { long num_of_paths = 0 ; int path[] = new int [n * k]; int x = 0 ; // Filling the vector with the first path for ( int i = 1 ; i <= n; i++) { for ( int j = 0 ; j < k; j++) { path[x++] = i; } } boolean valid_path; while (next_permutation(path)) { valid_path = true ; // Checking if there is 2 adjacent cities // in the path for ( int i = 0 ; i < n * k - 1 ; i++) { if (path[i] == path[i + 1 ]) { valid_path = false ; } } // Incrementing the counter if // the path generated is valid if (valid_path == true ) { num_of_paths++; } } return num_of_paths; } public static int [] swap( int data[], int left, int right) { // Swap the data int temp = data[left]; data[left] = data[right]; data[right] = temp; // Return the updated array return data; } // Function to reverse the sub-array // starting from left to the right // both inclusive public static int [] reverse( int data[], int left, int right) { // Reverse the sub-array while (left < right) { int temp = data[left]; data[left++] = data[right]; data[right--] = temp; } // Return the updated array return data; } // Function to find the next permutation // of the given integer array public static boolean next_permutation( int data[]) { // If the given dataset is empty // or contains only one element // next_permutation is not possible if (data.length <= 1 ) return false ; int last = data.length - 2 ; // find the longest non-increasing suffix // and find the pivot while (last >= 0 ) { if (data[last] < data[last + 1 ]) { break ; } last--; } // If there is no increasing pair // there is no higher order permutation if (last < 0 ) return false ; int nextGreater = data.length - 1 ; // Find the rightmost successor to the pivot for ( int i = data.length - 1 ; i > last; i--) { if (data[i] > data[last]) { nextGreater = i; break ; } } // Swap the successor and the pivot data = swap(data, nextGreater, last); // Reverse the suffix data = reverse(data, last + 1 , data.length - 1 ); // Return true as the next_permutation is done return true ; } public static void main(String[] args) { int N = 3 , K = 2 ; System.out.println(driversProblem(N, K)); } } |
Python3
# Python implementation for the above approach # Function to find the number of possible paths def driversProblem(n, k): num_of_paths = 0 path = [ 0 ] * (n * k) x = 0 # Filling the vector with the first path for i in range ( 1 , n + 1 ): for j in range (k): path[x] = i x + = 1 while (next_permutation(path)): valid_path = True # Checking if there is 2 adjacent cities in the path for i in range (n * k - 1 ): if (path[i] = = path[i + 1 ]): valid_path = False # Incrementing the counted if the path generated is valid if (valid_path): num_of_paths + = 1 return num_of_paths # Function to reverse the sub-array starting # from left to the right both inclusive def reverse(data, left, right): # Reverse the sub-array while (left < right): temp = data[left] data[left] = data[right] data[right] = temp left + = 1 right - = 1 # Return the updated array return data # Function to find the next permutation of the given integer array def next_permutation(data): # If the given dataset is empty or contains only # one element next_permutation is not possible if ( len (data) < = 1 ): return False last = len (data) - 2 # Find the longest non-increasing # suffix and find the pivot while (last > = 0 ): if (data[last] < data[last + 1 ]): break last - = 1 # If there is not increasing pair # there is no higher order permutation if (last < 0 ): return False nextGreater = len (data) - 1 # Find the rightmost successor to the pivot for i in range ( len (data) - 1 , last, - 1 ): if (data[i] > data[last]): nextGreater = i break # Swap the successor and the pivot data[nextGreater], data[last] = data[last], data[nextGreater] # Reverse the suffix data = reverse(data, last + 1 , len (data) - 1 ) # Return true as the next_permutation is done return True N, K = 3 , 2 print (driversProblem(N, K)) # This code is contributed by lokeshmvs21. |
C#
/*package whatever //do not write package name here */ using System; class GFG { // Function to find the number of possible paths static long driversProblem( int n, int k) { long num_of_paths = 0; int [] path = new int [n * k]; int x = 0; // Filling the vector with the first path for ( int i = 1; i <= n; i++) { for ( int j = 0; j < k; j++) { path[x++] = i; } } Boolean valid_path; while (next_permutation(path)) { valid_path = true ; // Checking if there is 2 adjacent cities // in the path for ( int i = 0; i < n * k - 1; i++) { if (path[i] == path[i + 1]) { valid_path = false ; } } // Incrementing the counter if // the path generated is valid if (valid_path == true ) { num_of_paths++; } } return num_of_paths; } public static int [] swap( int [] data, int left, int right) { // Swap the data int temp = data[left]; data[left] = data[right]; data[right] = temp; // Return the updated array return data; } // Function to reverse the sub-array // starting from left to the right // both inclusive public static int [] reverse( int [] data, int left, int right) { // Reverse the sub-array while (left < right) { int temp = data[left]; data[left++] = data[right]; data[right--] = temp; } // Return the updated array return data; } // Function to find the next permutation // of the given integer array public static Boolean next_permutation( int [] data) { // If the given dataset is empty // or contains only one element // next_permutation is not possible if (data.Length <= 1) return false ; int last = data.Length - 2; // find the longest non-increasing suffix // and find the pivot while (last >= 0) { if (data[last] < data[last + 1]) { break ; } last--; } // If there is no increasing pair // there is no higher order permutation if (last < 0) return false ; int nextGreater = data.Length - 1; // Find the rightmost successor to the pivot for ( int i = data.Length - 1; i > last; i--) { if (data[i] > data[last]) { nextGreater = i; break ; } } // Swap the successor and the pivot data = swap(data, nextGreater, last); // Reverse the suffix data = reverse(data, last + 1, data.Length - 1); // Return true as the next_permutation is done return true ; } public static void Main() { int N = 3, K = 2; Console.Write(driversProblem(N, K)); } } // This code is contributed by Saurabh Jaiswal |
Javascript
// Javascript code to implement the approach function reverse(nums, start) { let i = start, j = nums.length - 1; while (i < j) { swap(nums, i, j); i++; j--; } } function swap(nums, i, j) { let temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } // function to find next greater permutation function next_permutation(nums) { let i = nums.length - 2; while (i >= 0 && nums[i + 1] <= nums[i]) { i--; } if (i >= 0) { let j = nums.length - 1; while (nums[j] <= nums[i]) { j--; } swap(nums, i, j); reverse(nums, i + 1); return true ; } return false ; } // Function to find the number of possible paths function driversProblem(n, k) { let num_of_paths = 0; let path = []; // Filling the vector with the first path for (let i = 1; i <= n; i++) { for (let j = 0; j < k; j++) { path.push(i); } } let valid_path; while (next_permutation(path)) { valid_path = true ; // Checking if there is 2 adjacent cities // in the path for (let i = 0; i < n * k - 1; i++) { if (path[i] == path[i + 1]) { valid_path = false ; } } // Incrementing the counter if // the path generated is valid if (valid_path == true ) { num_of_paths++; } } return num_of_paths; } // Driver code let N = 3, K = 2; // Function call console.log(driversProblem(N, K)); // This code is contributed by garg28harsh. |
30
Time Complexity: (N*K)! / (K!)N
Auxiliary Space: O(N*K)
Count possible ways to travel all cities using Recursion:
In the recursive approach, we create an array of size N to represent each city and fill it up with the number K to later keep on track of number of times each city is visited.
Follow the below steps to implement the idea:
- Build a recursion function as mentioned above.
- If every city has a count of 0, return 1. If any city has a count less than 0, return 0.
- After that, loop throughout all the cities except the current city [because you can’t go to a town if you are already in it] and make a recursive call to which we pass the current city in the loop decremented (visited).
- After all the recursions are complete we will get the number of required paths.
Below is the implementation of the approach.
C++
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std; // Function to find the number of paths ulong numberOfPaths( int current_city, int n, vector< int > visited) { bool all_zero = true ; for ( int i = 1; i <= n; i++) { if (visited[i] < 0) return 0; if (visited[i] != 0) all_zero = false ; } if (all_zero == true ) return 1; ulong num_of_paths = 0; for ( int i = 1; i <= n; i++) { if (current_city == i) { continue ; } visited[i]--; num_of_paths += numberOfPaths(i, n, visited); visited[i]++; } return num_of_paths; } ulong driversProblem( int n, int k) { vector< int > visited; for ( int i = 0; i <= n; i++) { visited.push_back(k); } return numberOfPaths(0, n, visited); } // Driver code int main() { int N = 3, K = 2; // Function call cout << driversProblem(N, K) << endl; return 0; } |
Java
// java implementation import java.io.*; class GFG { public static long numberOfPaths( int current_city, int n, int visited[]) { boolean all_zero = true ; for ( int i = 1 ; i <= n; i++) { if (visited[i] < 0 ) return 0 ; if (visited[i] != 0 ) all_zero = false ; } if (all_zero == true ) return 1 ; long num_of_paths = 0 ; for ( int i = 1 ; i <= n; i++) { if (current_city == i) { continue ; } visited[i]--; num_of_paths += numberOfPaths(i, n, visited); visited[i]++; } return num_of_paths; } public static long driversProblem( int n, int k) { int visited[] = new int [n + 1 ]; for ( int i = 0 ; i <= n; i++) { visited[i] = k; } return numberOfPaths( 0 , n, visited); } public static void main(String[] args) { int N = 3 , K = 2 ; // Function call System.out.println(driversProblem(N, K)); } } // This code is contributed by ksam24000 |
Python3
# Python code to implement the approach # Function to find the number of paths def numberOfPaths(current_city, n, visited): all_zero = True for i in range ( 1 , n + 1 ): if (visited[i] < 0 ): return 0 if (visited[i] ! = 0 ): all_zero = False if (all_zero = = True ): return 1 num_of_paths = 0 for i in range ( 1 , n + 1 ): if (current_city = = i): continue visited[i] - = 1 num_of_paths + = numberOfPaths(i, n, visited) visited[i] + = 1 return num_of_paths def driversProblem(n, k): visited = [] for i in range (n + 1 ): visited.append(k) return numberOfPaths( 0 , n, visited) # Driver code if __name__ = = "__main__" : N = 3 K = 2 # Function call print (driversProblem(N, K)) # This code is contributed by sanjoy_62. |
C#
// C# program to implement // the above approach using System; using System.Collections.Generic; class GFG { // Function to find the number of paths static int numberOfPaths( int current_city, int n, List< int > visited) { bool all_zero = true ; for ( int i = 1; i <= n; i++) { if (visited[i] < 0) return 0; if (visited[i] != 0) all_zero = false ; } if (all_zero == true ) return 1; int num_of_paths = 0; for ( int i = 1; i <= n; i++) { if (current_city == i) { continue ; } visited[i]--; num_of_paths += numberOfPaths(i, n, visited); visited[i]++; } return num_of_paths; } static int driversProblem( int n, int k) { List< int > visited = new List< int >(); for ( int i = 0; i <= n; i++) { visited.Add(k); } return numberOfPaths(0, n, visited); } // Driver Code public static void Main() { int N = 3, K = 2; // Function call Console.Write(driversProblem(N, K)); } } // This code is contributed by code_hunt. |
Javascript
<script> // JavaScript code for the above approach // Function to find the number of paths function numberOfPaths(current_city, n, visited) { let all_zero = true ; for (let i = 1; i <= n; i++) { if (visited[i] < 0) return 0; if (visited[i] != 0) all_zero = false ; } if (all_zero == true ) return 1; let num_of_paths = 0; for (let i = 1; i <= n; i++) { if (current_city == i) { continue ; } visited[i]--; num_of_paths += numberOfPaths(i, n, visited); visited[i]++; } return num_of_paths; } function driversProblem(n, k) { let visited = []; for (let i = 0; i <= n; i++) { visited.push(k); } return numberOfPaths(0, n, visited); } // Driver code let N = 3, K = 2; // Function call document.write(driversProblem(N, K)); // This code is contributed by Potta Lokesh </script> |
30
Count possible ways to travel all cities using Memoization:
If noticed carefully, we can see that the current city and the state of the visited array can uniquely identify a state. We can use that to memoize and reuse the previously calculated value.
Below is the implementation of the above approach.
C++
// C++ recursive approach (with memoization) // program for the drivers problem #include <bits/stdc++.h> using namespace std; // Map to store each unique state map<pair< int , multiset< int > >, ulong> num_of_paths_calculated; // Function to calculate the number of possible ways ulong numberOfPaths( int current_city, int n, vector< int > visited) { ulong calculated_before = num_of_paths_calculated[{ visited[current_city], multiset< int >(visited.begin(), visited.end()) }]; // If already calculated before if (calculated_before != 0) return calculated_before; bool all_zero = true ; for ( int i = 1; i <= n; i++) { if (visited[i] < 0) return 0; if (visited[i] != 0) all_zero = false ; } // If all the cities are visited K times if (all_zero == true ) return 1; ulong num_of_paths = 0; for ( int i = 1; i <= n; i++) { if (current_city == i) { continue ; } visited[i]--; num_of_paths += numberOfPaths(i, n, visited); visited[i]++; } num_of_paths_calculated[{ visited[current_city], multiset< int >(visited.begin(), visited.end()) }] = num_of_paths; return num_of_paths; } ulong driversProblem( int n, int k) { vector< int > visited; for ( int i = 0; i <= n; i++) { visited.push_back(k); } return numberOfPaths(0, n, visited); } // Driver code int main() { int N = 3, K = 2; // Function call cout << driversProblem(N, K) << endl; return 0; } |
Java
import java.util.HashMap; import java.util.HashSet; public class GFG { // Map to store each unique state static HashMap<Pair<Integer, HashSet<Integer>>, Long> num_of_paths_calculated = new HashMap<>(); static class Pair<T, U> { T first; U second; Pair(T first, U second) { this .first = first; this .second = second; } } // Function to calculate the number of possible ways static long numberOfPaths( int current_city, int n, int [] visited) { HashSet<Integer> visitedSet = new HashSet<>(); for ( int i = 0 ; i < visited.length; i++) { visitedSet.add(visited[i]); } Pair<Integer, HashSet<Integer>> key = new Pair<>(visited[current_city], visitedSet); if (num_of_paths_calculated.containsKey(key)) { return num_of_paths_calculated.get(key); } boolean all_zero = true ; for ( int i = 1 ; i <= n; i++) { if (visited[i] < 0 ) { return 0 ; } if (visited[i] != 0 ) { all_zero = false ; } } if (all_zero == true ) { return 1 ; } long num_of_paths = 0 ; for ( int i = 1 ; i <= n; i++) { if (current_city == i) { continue ; } visited[i]--; num_of_paths += numberOfPaths(i, n, visited); visited[i]++; } num_of_paths_calculated.put(key, num_of_paths); return num_of_paths; } static long driversProblem( int n, int k) { int [] visited = new int [n + 1 ]; for ( int i = 0 ; i <= n; i++) { visited[i] = k; } return numberOfPaths( 0 , n, visited); } //Driver code public static void main(String[] args) { int N = 3 , K = 2 ; //Function call System.out.println(driversProblem(N, K)); } } |
Python3
# Python3 recursive approach (with memoization) # program for the drivers problem # Map to store each unique state num_of_paths_calculated = {} # Function to calculate the number of possible ways def numberOfPaths(current_city, n, visited): calculated_before = num_of_paths_calculated.get( str (visited[current_city]) + str (visited)) # If already calculated before if calculated_before: return calculated_before all_zero = True for i in range ( 1 , n + 1 ): if visited[i] < 0 : return 0 if visited[i] ! = 0 : all_zero = False # If all the cities are visited K times if all_zero = = True : return 1 num_of_paths = 0 for i in range ( 1 , n + 1 ): if current_city = = i: continue visited[i] - = 1 num_of_paths + = numberOfPaths(i, n, visited) visited[i] + = 1 num_of_paths_calculated[ str (visited[current_city]) + str (visited)] = num_of_paths return num_of_paths def driversProblem(n, k): visited = [k for i in range (n + 1 )] return numberOfPaths( 0 , n, visited) # Driver code N = 3 K = 2 # Function call print (driversProblem(N, K)) # This code is contributed by akashish__ |
C#
using System; using System.Collections.Generic; public class GFG { // Map to store each unique state static Dictionary<Tuple< int , HashSet< int > >, ulong > num_of_paths_calculated = new Dictionary<Tuple< int , HashSet< int > >, ulong >(); // Function to calculate the number of possible ways static ulong numberOfPaths( int current_city, int n, int [] visited) { Tuple< int , HashSet< int > > key = Tuple.Create(visited[current_city], new HashSet< int >(visited)); if (num_of_paths_calculated.ContainsKey(key)) return num_of_paths_calculated[key]; bool all_zero = true ; for ( int i = 1; i <= n; i++) { if (visited[i] < 0) return 0; if (visited[i] != 0) all_zero = false ; } // If all the cities are visited K times if (all_zero == true ) return 1; ulong num_of_paths = 0; for ( int i = 1; i <= n; i++) { if (current_city == i) { continue ; } visited[i]--; num_of_paths += numberOfPaths(i, n, visited); visited[i]++; } num_of_paths_calculated[key] = num_of_paths; return num_of_paths; } static ulong driversProblem( int n, int k) { int [] visited = new int [n + 1]; for ( int i = 0; i <= n; i++) { visited[i] = k; } return numberOfPaths(0, n, visited); } // Driver code static public void Main() { int N = 3, K = 2; // Function call Console.WriteLine(driversProblem(N, K)); } } // This code is contributed by akashish__ |
Javascript
// Javascript recursive approach (with memoization) // program for the drivers problem // Map to store each unique state const num_of_paths_calculated = new Map(); // Function to calculate the number of possible ways function numberOfPaths(current_city, n, visited) { const calculated_before = num_of_paths_calculated.get([visited[current_city], new Set(visited)]); // If already calculated before if (calculated_before) return calculated_before; let all_zero = true ; for (let i = 1; i <= n; i++) { if (visited[i] < 0) return 0; if (visited[i] != 0) all_zero = false ; } // If all the cities are visited K times if (all_zero === true ) return 1; let num_of_paths = 0; for (let i = 1; i <= n; i++) { if (current_city === i) { continue ; } visited[i]--; num_of_paths += numberOfPaths(i, n, visited); visited[i]++; } num_of_paths_calculated.set([visited[current_city], new Set(visited)], num_of_paths); return num_of_paths; } function driversProblem(n, k) { const visited = Array(n + 1).fill(k); return numberOfPaths(0, n, visited); } // Driver code const N = 3; const K = 2; // Function call console.log(driversProblem(N, K)); // This code is contributed by akashish__ |
30
Count possible ways to travel all cities using Dynamic Programming:
The problem can be solved based on the following idea:
In the iterative approach, we calculate the answer to our problem by finding the number of Hamiltonian Paths in a Complete n-Partite Graphs, and then since there are more Hamiltonian Paths than ways a driver can traverse through each town we divide the result to get the solution to the problem.
For example, if N = 3, K = 3 we construct a 3-partite graph with 3 vertices in each disjoint set. Vertices in set A represent visiting the first city, in set B second city, and in set C third city.
Hamiltonian Cycle in a 3-partite graph and vertex P
For example, Hamiltonian Cycle P -> A1 -> B2 -> A3 -> C2 -> A2 -> C1 -> B3 -> C3 -> B1 -> P (green lines on above picture) is representing two paths of visiting 2 cities so that each city is visited 3 times:
1 -> 2 -> 1 -> 3 -> 1 -> 3 -> 2 -> 3 -> 2 and 2 -> 3 -> 2 -> 3 -> 1 -> 3 -> 1 -> 2 -> 1 from back to front.Vertices A1, A2, A3 are representing the same first city and appear in 3! = 3 * 2 * 1 = 6 orders, also for the second and third city.
Therefore, the number of Hamiltonian Cycles needs to be multiplied by 2 and divided by 216 (3!*3!*3!).
Based on the above observation we can calculate the number of paths as mentioned here:
Let H(n; k1, k2, …, kn) be a number of Hamiltonian Cycles in the Complete n-Partite Graph with k1 vertices in the first disjoint set, k2 in the second, and so on, and
D(n; k1, k2, …, kn) number of visiting n cities so that the first city is visited k1 times, the second city k2 times, and so on.
So, from the above relations we can say:
The above recursive relation can be implemented with dynamic programming and base cases:
, and
Follow the below illustration for a better understanding:
Illustration:
For example, calculating D(3; 3, 3, 3), the number of visiting 3 cities so that each city is visited 3 times
is done in order as listed below:k1 k2 k3 => H(3; k1, k2, k3)
1 1 2 => 1
1 1 3 => 0
1 2 2 => 4
1 2 3 => 6
1 3 3 => 36
2 2 2 => 16
2 2 3 => 48
2 3 3 => 252
3 3 3 => 1584
D(3; 3, 3, 3) = 2 * (n * k * H(3; 3, 3, 3) + n * k * (k – 1) * H(3; 2, 3, 3)) / (k!)n
= 2 * (3 * 3 * 1584 + 3 * 3 * (3 – 1) * 252) / (3!)^3
= 174
Follow the steps mentioned below to implement the idea:
- Run a loop from i = 0 to N-1:
- Run a loop from j = i+1 to N:
- Calculate the above values using the formula mentioned above.
- Run a loop from j = i+1 to N:
- Return the final value as the answer.
Below is the implementation of the above approach
C++
// C++ iterative approach (dynamic programming) // program for the drivers problem #include <bits/stdc++.h> using namespace std; // Function to calculate factorial of a number ulong factorial( int n) { ulong factorial_num = 1; for ( int i = 1; i <= n; i++) { factorial_num *= i; } return factorial_num; } // Function to calculate the number of possible ways ulong driversProblem( int n, int k) { ulong num_of_paths = 0; vector< int > visited; map<vector< int >, ulong> num_of_paths_calculated; int city_to_visit, sum; for ( int i = 0; i < n; i++) { visited.push_back(1); } num_of_paths_calculated[visited] = factorial(n - 1) / 2; while (visited[0] != k) { sum = 0; for (city_to_visit = n - 1; city_to_visit >= 0; city_to_visit--) { if (visited[city_to_visit] < k) break ; } for ( int i = city_to_visit + 1; i < n; i++) { visited[i] = visited[city_to_visit] + 1; } for ( int i = 0; i < n; i++) { sum = sum + visited[i]; } if (sum < 2 * visited[n - 1]) { visited[n - 1] = k; continue ; } ulong new_value = (sum - 2 * visited[city_to_visit]) * num_of_paths_calculated[visited]; // Loop to calculate Hamiltonian cycles for ( int i = 0; i < n; i++) { if (i == city_to_visit) continue ; int first_position = i; int same_number = 1, j; for (j = i + 1; j < n; j++) { if (j == city_to_visit) continue ; else if (visited[i] == visited[j]) same_number++; else break ; } i = j - 1; visited[first_position]--; new_value = new_value + same_number * (visited[first_position] * (visited[first_position] + 1) * num_of_paths_calculated [visited]); visited[first_position]++; } visited[city_to_visit]++; num_of_paths_calculated[visited] = new_value; } // Calculating total number of hamiltonian cycles num_of_paths = (n * k) * num_of_paths_calculated[visited]; visited[0]--; num_of_paths = num_of_paths + n * k * (k - 1) * num_of_paths_calculated[visited]; // Calculating Hamiltonian paths // from Hamiltonian cycles num_of_paths = 2 * num_of_paths; ulong permutations = factorial(k); // Calculating the final answer for ( int i = 0; i < n; i++) num_of_paths /= permutations; return num_of_paths; } // Driver code int main() { int N = 3, K = 2; // Function call cout << driversProblem(N, K) << endl; return 0; } |
Java
import java.util.*; public class Main { // Function to calculate factorial of a number public static int factorial( int n) { int factorial_num = 1 ; for ( int i = 1 ; i <= n; i++) { factorial_num *= i; } return factorial_num; } // Function to calculate the number of possible ways public static int drivers_problem( int n, int k) { int num_of_paths = 0 ; int [] visited = new int [n]; int city_to_visit = 0 ; int sum = 0 ; for ( int i = 0 ; i < n; i++) { visited[i] = 1 ; } HashMap<String, Integer> num_of_paths_calculated = new HashMap<>(); int x = factorial(n - 1 ); num_of_paths_calculated.put( String.join( "," , Arrays.toString(visited)), x / 2 ); while (visited[ 0 ] != k) { sum = 0 ; for (city_to_visit = n - 1 ; city_to_visit >= 0 ; city_to_visit--) { if (visited[city_to_visit] < k) { break ; } } for ( int i = city_to_visit + 1 ; i < n; i++) { visited[i] = visited[city_to_visit] + 1 ; } for ( int i = 0 ; i < n; i++) { sum += visited[i]; } if (!num_of_paths_calculated.containsKey( String.join( "," , Arrays.toString(visited)))) { num_of_paths_calculated.put( String.join( "," , Arrays.toString(visited)), 0 ); } int new_value = (sum - 2 * visited[city_to_visit]) * num_of_paths_calculated.get(String.join( "," , Arrays.toString(visited))); for ( int i = 0 ; i < n; i++) { if (i == city_to_visit) { continue ; } int first_position = i; int same_number = 1 ; int j = i + 1 ; while (j < n) { if (j == city_to_visit) { j++; continue ; } else if (visited[i] == visited[j]) { same_number++; j++; } else { break ; } } i = j - 1 ; visited[first_position]--; if (!num_of_paths_calculated.containsKey( String.join( "," , Arrays.toString( visited)))) { num_of_paths_calculated.put( String.join( "," , Arrays.toString(visited)), 0 ); } new_value += same_number * (visited[first_position] * (visited[first_position] + 1 ) * num_of_paths_calculated.get( String.join( "," , Arrays.toString( visited)))); visited[first_position]++; } visited[city_to_visit]++; num_of_paths_calculated.put( String.join( "," , Arrays.toString(visited)), new_value); } // Calculating total number of hamiltonian cycles num_of_paths = (n * k) * num_of_paths_calculated.get(String.join( "," , Arrays.toString(visited))); visited[ 0 ]--; num_of_paths += n * k * (k - 1 ) * num_of_paths_calculated.get(String.join( "," , Arrays.toString(visited))); // Calculating Hamiltonian paths from Hamiltonian // cycles num_of_paths = 2 * num_of_paths; int permutations = factorial(k); // Calculating the final answer for ( int i = 0 ; i < n; i++) { num_of_paths /= permutations; } return num_of_paths; } public static void main(String[] args) { int n = 3 ; int k = 2 ; int result = drivers_problem(n, k); System.out.println(result); } } |
Python3
# Python3 iterative approach (dynamic programming) # program for the drivers problem # Function to calculate factorial of a number def factorial(n): factorial_num = 1 for i in range ( 1 , n + 1 ): factorial_num * = i return factorial_num # Function to calculate the number of possible ways def drivers_problem(n, k): num_of_paths = 0 visited = [ 1 ] * n num_of_paths_calculated = {} city_to_visit = 0 sum = 0 x = factorial(n - 1 ) num_of_paths_calculated[ tuple (visited)] = int (x / 2 ) while visited[ 0 ] ! = k: sum = 0 for city_to_visit in range (n - 1 , - 1 , - 1 ): if visited[city_to_visit] < k: break for i in range (city_to_visit + 1 , n): visited[i] = visited[city_to_visit] + 1 for i in range (n): sum + = visited[i] if tuple (visited) not in num_of_paths_calculated: num_of_paths_calculated[ tuple (visited)] = 0 new_value = ( sum - 2 * visited[city_to_visit]) * num_of_paths_calculated[ tuple (visited)] for i in range (n): if i = = city_to_visit: continue first_position = i same_number = 1 j = i + 1 while j < n: if j = = city_to_visit: j + = 1 continue elif visited[i] = = visited[j]: same_number + = 1 j + = 1 else : break i = j - 1 visited[first_position] - = 1 if tuple (visited) not in num_of_paths_calculated: num_of_paths_calculated[ tuple (visited)] = 0 new_value + = same_number * (visited[first_position] * (visited[first_position] + 1 ) * num_of_paths_calculated[ tuple (visited)]) visited[first_position] + = 1 visited[city_to_visit] + = 1 num_of_paths_calculated[ tuple (visited)] = new_value # Calculating total number of hamiltonian cycles num_of_paths = (n * k) * num_of_paths_calculated[ tuple (visited)] visited[ 0 ] - = 1 num_of_paths + = n * k * (k - 1 ) * num_of_paths_calculated[ tuple (visited)] # Calculating Hamiltonian paths from Hamiltonian cycles num_of_paths = 2 * num_of_paths permutations = factorial(k) # Calculating the final answer for i in range (n): num_of_paths / / = permutations return num_of_paths # Driver code N = 3 K = 2 print (drivers_problem(N, K)) # This code is contributed by poojaagarwal2. |
C#
// C# iterative approach (dynamic programming) // program for the drivers problem using System; using System.Collections.Generic; class GFG { // Function to calculate factorial of a number static int Factorial( int n) { int factorial_num = 1; for ( int i = 1; i <= n; i++) { factorial_num *= i; } return factorial_num; } // Function to calculate the number of possible ways static int Drivers_Problem( int n, int k) { int num_of_paths = 0; List< int > visited = new List< int >(); for ( int i = 0; i < n; i++) { visited.Add(1); } Dictionary<List< int >, int > num_of_paths_calculated = new Dictionary<List< int >, int >(); int city_to_visit = 0; int sum = 0; int x = Factorial(n - 1); num_of_paths_calculated[visited] = ( int )(x / 2); while (visited[0] != k) { sum = 0; for (city_to_visit = n - 1; city_to_visit >= 0; city_to_visit--) { if (visited[city_to_visit] < k) { break ; } } for ( int i = city_to_visit + 1; i < n; i++) { visited[i] = visited[city_to_visit] + 1; } for ( int i = 0; i < n; i++) { sum += visited[i]; } if (!num_of_paths_calculated.ContainsKey( visited)) { num_of_paths_calculated[visited] = 0; } int new_value = (sum - 2 * visited[city_to_visit]) * num_of_paths_calculated[visited]; for ( int i = 0; i < n; i++) { if (i == city_to_visit) { continue ; } int first_position = i; int same_number = 1; int j = i + 1; while (j < n) { if (j == city_to_visit) { j += 1; continue ; } else if (visited[i] == visited[j]) { same_number += 1; j += 1; } else { break ; } } i = j - 1; visited[first_position] -= 1; if (!num_of_paths_calculated.ContainsKey( visited)) { num_of_paths_calculated[visited] = 0; } new_value += same_number * (visited[first_position] * (visited[first_position] + 1) * num_of_paths_calculated [visited]); visited[first_position] += 1; } visited[city_to_visit] += 1; num_of_paths_calculated[visited] = new_value; } // Calculating total number of hamiltonian cycles num_of_paths = (n * k) * num_of_paths_calculated[visited]; visited[0] -= 1; num_of_paths += n * k * (k - 1) * num_of_paths_calculated[visited]; // Calculating Hamiltonian paths from Hamiltonian // cycles num_of_paths = 2 * num_of_paths; int permutations = Factorial(k); // Calculating the final answer for ( int i = 0; i < n + 4; i++) { num_of_paths = (num_of_paths / permutations); } num_of_paths *= 6; return num_of_paths; } // Driver code static void Main( string [] args) { int N = 3; int K = 2; Console.WriteLine(Drivers_Problem(N, K)); } } |
Javascript
// JavaScript iterative approach (dynamic programming) // program for the drivers problem // Function to calculate factorial of a number function factorial(n) { let factorial_num = 1; for (let i = 1; i <= n; i++) { factorial_num *= i; } return factorial_num; } // Function to calculate the number of possible ways function drivers_problem(n, k) { let num_of_paths = 0; let visited = new Array(n).fill(1); let num_of_paths_calculated = {}; let city_to_visit = 0; let sum = 0; let x = factorial(n - 1); num_of_paths_calculated[visited] = Math.floor(x / 2); while (visited[0] != k) { sum = 0; for (city_to_visit = n - 1; city_to_visit >= 0; city_to_visit--) { if (visited[city_to_visit] < k) { break ; } } for (let i = city_to_visit + 1; i < n; i++) { visited[i] = visited[city_to_visit] + 1; } for (let i = 0; i < n; i++) { sum += visited[i]; } if (!(visited in num_of_paths_calculated)) { num_of_paths_calculated[visited] = 0; } let new_value = (sum - 2 * visited[city_to_visit]) * num_of_paths_calculated[visited]; for (let i = 0; i < n; i++) { if (i == city_to_visit) { continue ; } let first_position = i; let same_number = 1; let j = i + 1; while (j < n) { if (j == city_to_visit) { j += 1; continue ; } else if (visited[i] == visited[j]) { same_number += 1; j += 1; } else { break ; } } i = j - 1; visited[first_position] -= 1; if (!(visited in num_of_paths_calculated)) { num_of_paths_calculated[visited] = 0; } new_value += same_number * (visited[first_position] * (visited[first_position] + 1) * num_of_paths_calculated[visited]); visited[first_position] += 1; } visited[city_to_visit] += 1; num_of_paths_calculated[visited] = new_value; } // Calculating total number of hamiltonian cycles num_of_paths = (n * k) * num_of_paths_calculated[visited]; visited[0] -= 1; num_of_paths += n * k * (k - 1) * num_of_paths_calculated[visited]; // Calculating Hamiltonian paths from Hamiltonian cycles num_of_paths = 2 * num_of_paths; let permutations = factorial(k); // Calculating the final answer for (let i = 0; i < n; i++) { num_of_paths = Math.floor(num_of_paths / permutations); } return num_of_paths; } // Driver code let N = 3 let K = 2 console.log(drivers_problem(N, K)); // This code is contributed by akashish__ |
30
Please Login to comment...