forked from TheAlgorithms/Rust
-
Notifications
You must be signed in to change notification settings - Fork 0
[pull] master from TheAlgorithms:master #214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
src/dynamic_programming/task_assignment.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| // Task Assignment Problem using Bitmasking and DP in Rust | ||
| // Time Complexity: O(2^M * N) where M is number of people and N is number of tasks | ||
| // Space Complexity: O(2^M * N) for the DP table | ||
|
|
||
| use std::collections::HashMap; | ||
|
|
||
| /// Solves the task assignment problem where each person can do only certain tasks, | ||
| /// each person can do only one task, and each task is performed by only one person. | ||
| /// Uses bitmasking and dynamic programming to count total number of valid assignments. | ||
| /// | ||
| /// # Arguments | ||
| /// * `task_performed` - A vector of vectors where each inner vector contains tasks | ||
| /// that a person can perform (1-indexed task numbers) | ||
| /// * `total_tasks` - The total number of tasks (N) | ||
| /// | ||
| /// # Returns | ||
| /// * The total number of valid task assignments | ||
| pub fn count_task_assignments(task_performed: Vec<Vec<usize>>, total_tasks: usize) -> i64 { | ||
| let num_people = task_performed.len(); | ||
| let dp_size = 1 << num_people; | ||
|
|
||
| // Initialize DP table with -1 (uncomputed) | ||
| let mut dp = vec![vec![-1; total_tasks + 2]; dp_size]; | ||
|
|
||
| let mut task_map = HashMap::new(); | ||
| let final_mask = (1 << num_people) - 1; | ||
|
|
||
| // Build the task -> people mapping | ||
| for (person, tasks) in task_performed.iter().enumerate() { | ||
| for &task in tasks { | ||
| task_map.entry(task).or_insert_with(Vec::new).push(person); | ||
| } | ||
| } | ||
|
|
||
| // Recursive DP function | ||
| fn count_ways_until( | ||
| dp: &mut Vec<Vec<i64>>, | ||
| task_map: &HashMap<usize, Vec<usize>>, | ||
| final_mask: usize, | ||
| total_tasks: usize, | ||
| mask: usize, | ||
| task_no: usize, | ||
| ) -> i64 { | ||
| // Base case: all people have been assigned tasks | ||
| if mask == final_mask { | ||
| return 1; | ||
| } | ||
|
|
||
| // Base case: no more tasks available but not all people assigned | ||
| if task_no > total_tasks { | ||
| return 0; | ||
| } | ||
|
|
||
| // Return cached result if already computed | ||
| if dp[mask][task_no] != -1 { | ||
| return dp[mask][task_no]; | ||
| } | ||
|
|
||
| // Option 1: Skip the current task | ||
| let mut total_ways = | ||
| count_ways_until(dp, task_map, final_mask, total_tasks, mask, task_no + 1); | ||
|
|
||
| // Option 2: Assign current task to a capable person who isn't busy | ||
| if let Some(people) = task_map.get(&task_no) { | ||
| for &person in people { | ||
| // Check if this person is already assigned a task | ||
| if mask & (1 << person) != 0 { | ||
| continue; | ||
| } | ||
|
|
||
| // Assign task to this person and recurse | ||
| total_ways += count_ways_until( | ||
| dp, | ||
| task_map, | ||
| final_mask, | ||
| total_tasks, | ||
| mask | (1 << person), | ||
| task_no + 1, | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| // Cache the result | ||
| dp[mask][task_no] = total_ways; | ||
| total_ways | ||
| } | ||
|
|
||
| // Start recursion with no people assigned and first task | ||
| count_ways_until(&mut dp, &task_map, final_mask, total_tasks, 0, 1) | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| // Macro to generate multiple test cases for the task assignment function | ||
| macro_rules! task_assignment_tests { | ||
| ($($name:ident: $input:expr => $expected:expr,)*) => { | ||
| $( | ||
| #[test] | ||
| fn $name() { | ||
| let (task_performed, total_tasks) = $input; | ||
| assert_eq!(count_task_assignments(task_performed, total_tasks), $expected); | ||
| } | ||
| )* | ||
| }; | ||
| } | ||
|
|
||
| task_assignment_tests! { | ||
| test_case_1: (vec![vec![1, 3, 4], vec![1, 2, 5], vec![3, 4]], 5) => 10, | ||
| test_case_2: (vec![vec![1, 2], vec![1, 2]], 2) => 2, | ||
| test_case_3: (vec![vec![1], vec![2], vec![3]], 3) => 1, | ||
| test_case_4: (vec![vec![1, 2, 3], vec![1, 2, 3], vec![1, 2, 3]], 3) => 6, | ||
| test_case_5: (vec![vec![1], vec![1]], 1) => 0, | ||
|
|
||
| // Edge test case | ||
| test_case_single_person: (vec![vec![1, 2, 3]], 3) => 3, | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.