diff --git a/05- May/13- Count Ways To Build Good Strings/13- Count Ways To Build Good Strings (Mahmoud Aboelsoud).cpp b/05- May/13- Count Ways To Build Good Strings/13- Count Ways To Build Good Strings (Mahmoud Aboelsoud).cpp new file mode 100644 index 000000000..4dcd1b7bf --- /dev/null +++ b/05- May/13- Count Ways To Build Good Strings/13- Count Ways To Build Good Strings (Mahmoud Aboelsoud).cpp @@ -0,0 +1,49 @@ +// Author: Mahmoud Aboelsoud + +class Solution { +public: + // we need to count the number of ways to build a string of length between low and high + // we will use dp to count the number of ways to build a string of length n + // we will use a recursive function to count the number of ways to build a string of length n + // the recursive function will return 0 if n > high + + + // dp: dp[i] -> number of ways to build a string of length i + // low: the minimum length of the string + // high: the maximum length of the string + // zero: the number of zeros you can append to the string + // one: the number of ones you can append to the string + int dp[100005], low, high, zero, one, mod = 1e9 + 7; + + // recursive function to count the number of ways to build a string of length n + int cnt_ways(int n){ + // if n > high return 0 + if(n > high) return 0; + + // if n is calculated before return the value + if(dp[n] != -1) return dp[n]; + + // if n is in the range [low, high] then add 1 to the answer + int ans = (n >= low); + + // add the number of ways to build a string of length n + zero + ans += cnt_ways(n + zero); + ans %= mod; + // add the number of ways to build a string of length n + one + ans += cnt_ways(n + one); + ans %= mod; + + // return the answer + return dp[n] = ans; + } + + int countGoodStrings(int low, int high, int zero, int one){ + // initialize dp with -1 + memset(dp, -1, sizeof(dp)); + // initialize the global variables + this -> low = low, this -> high = high, this -> zero = zero, this -> one = one; + + // return the number of ways to build a string of length between low and high starting from length 0 + return cnt_ways(0); + } +}; diff --git a/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Ahmed Hossam).cpp b/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Ahmed Hossam).cpp new file mode 100644 index 000000000..5ce3a0d5c --- /dev/null +++ b/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Ahmed Hossam).cpp @@ -0,0 +1,49 @@ +// Author: Ahmed Hossam + +class Solution { +public: + + // declare variables + int n, full_mask; + // vectors to store numbers and dynamic programming results + vector nums, dp; + + // function to check if a bit is empty in a binary mask + bool is_empty_bit(int bit, int mask){ + return !(mask & (1 << bit)); + } + + // recursive function to calculate the maximum score + int max_score(int mask){ + // if all bits are filled, return 0 + if(mask == full_mask) return 0; + // use memoization to avoid redundant computations + int& ret = dp[mask]; + // calculate the current index based on the number of filled bits + int idx = __builtin_popcount(mask) / 2 + 1; + // if the result has already been calculated, return it + if(~ret) return ret; + ret = 0; + // iterate over all pairs of numbers + for(int i = 0; i < n; i++) + for(int j = i + 1; j < n; j++) + // if both numbers are empty, calculate the score + if(is_empty_bit(i, mask) && is_empty_bit(j, mask)) + ret = max(ret, (idx * __gcd(nums[i], nums[j])) + max_score(mask | (1 << i) | (1 << j))); + // return the maximum score + return ret; + } + + int maxScore(vector& nums) { + // set the number of elements + n = nums.size(); + // set the vector of numbers + this -> nums = nums; + // set the full binary mask + full_mask = (1 << n) - 1; + // initialize the dynamic programming vector with -1 + dp = vector(1 << n, -1); + // return the maximum score starting with an empty mask + return max_score(0); + } +}; diff --git a/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Lama Salah).cpp b/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Lama Salah).cpp new file mode 100644 index 000000000..51b2c0d31 --- /dev/null +++ b/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Lama Salah).cpp @@ -0,0 +1,56 @@ +// Author: Lama Salah + +class Solution { +public: + // Declare the size of the list and memoization array. + int n, memo[8][100000]; + + int dp(int i, int mask, vector & nums){ + // If we've performed all operations, return 0 - (the base-case). + if (i > n) return 0; + + // Get a reference to the memoized result for this i and mask and check if the result is already memoized. + int& ans = memo[i][mask]; + if (~ans) return ans; + + // Loop over all possible unremoved pairs. + for (int k = 0; k < 2*n; k++){ + // Check if the k-th bit in the mask is 0 (the k-th integer has not been removed). + if (!((mask >> k) & 1)){ + // Set the k-th bit in the mask to 1 (remove the k-th integer). + mask |= (1 << k); + + // Loop over all possible unremoved integers. + for (int l = 0; l < 2*n; l++){ + // check If the l-th bit in the mask is 0 (the l-th integer has not been removed). + if (!((mask >> l) & 1)){ + + // Set the l-th bit in the mask to 1 (remove the l-th integer). + mask |= (1 << l); + + // Compute the score for using the k-th and l-th integers. + ans = max(ans, (i* gcd(nums[k], nums[l])) + dp(i+1, mask, nums)); + + // Unset the l-th bit in the mask. + mask ^= (1 << l); + } + } + + // Unset the k-th bit in the mask. + mask ^= (1 << k); + } + } + + return ans; + } + + int maxScore(vector& nums) { + this -> n = nums.size()/2; + + // Initialize the memo array with -1 values using the memset() function. + memset(memo, -1, sizeof memo); + + // Compute the maximum score after N operations. + return dp(1, 0, nums); + } +}; diff --git a/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Mohamed Emara).cpp b/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Mohamed Emara).cpp new file mode 100644 index 000000000..879868b30 --- /dev/null +++ b/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Mohamed Emara).cpp @@ -0,0 +1,64 @@ + +// Author: MohamedEmara + +class Solution { +public: + + int n; + int dp[20][20000]; + int arr[20]; + + int rec(int idx, int mask) + { + // the base case WHEN all bits are set to one + if(mask == (1<<(2*n))-1) + return 0; + + int &ret = dp[idx][mask]; + if(~ret) + return ret; + + + ret = 0; + + for(int i=0; i<2*n; i++) + { + for(int j=i+1; j<2*n; j++) + { + // if the two bits i , j not taken yet in the mask + // try to take them and maximize the value. + if(!(mask & (1 << j)) && !(mask & (1 << i))) + { + // set two bits of one ie: add the value of these two bits + int tmp = mask + (1 << j) + (1 << i); + ret = fmax(ret, idx * __gcd(arr[i], arr[j]) + rec(idx+1, tmp)); + } + } + } + + return ret; + } + + + int maxScore(vector& nums) { + ios_base::sync_with_stdio(false); +cin.tie(NULL); + + + n = nums.size() / 2; + + // At every idx(ith operation) + // We will try to choose two distinct numbers + // An save the taken elements in a mask that is intially all zeros + // the two taken element --> set their bits to one and continue trying other elements + // till the mask becoms all ones of lenght 2*N --> (1 << (2*n) - 1) + + memset(dp, -1, sizeof(dp)); + for(int i=0; i<2*n; i++) + arr[i] = nums[i]; + + return rec(1, 0); + } +}; + + diff --git a/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Omar Sanad).cpp b/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Omar Sanad).cpp new file mode 100644 index 000000000..bcae90d85 --- /dev/null +++ b/05- May/14- Maximize Score After N Operations/14- Maximize Score After N Operations (Omar Sanad).cpp @@ -0,0 +1,55 @@ +// author : Omar Sanad + +class Solution { +public: + // declare the array nums in the class itslef, to use it anywhere in the class + vector < int > nums; + + // declare a 2D array for the memoization + // declare the number of steps (n) + // declare the size of the array which equals 2 * n + int dp[15][1 << 14], n, the_sz; + int rec(int idx, int mask) { + + // if we've already done the n operations, then we return + if (idx > n) + return 0; + + // assign the dp[idx][mask] to ret by reference to use it easily + int &ret = dp[idx][mask]; + + // if this state was already been calculated, then we return its answer + if (~ret) return ret; + + // otherwise we initialize the answer with 0 + ret = 0; + + // we iterate over the elements of the array, and for every two unvisited elements we try taking them for this step + for (int i = 0; i < the_sz; i++) + if ((mask & (1 << i)) == 0) + for (int j = i + 1; j < the_sz; j++) + if ((mask & (1 << j)) == 0) + // if we try to take nums[i], nums[j] + // then we mark them as visited in the mask --> mask | (1 << j) | (1 << i) + ret = max(ret, idx * gcd(nums[i], nums[j]) + rec(idx + 1, mask | (1 << j) | (1 << i))); + + + // return the answer for this state + return ret; + } + int maxScore(vector& nums) { + + // assign the passed array nums to the array nums which is declared inside the class itself + this->nums = nums; + + this->the_sz = nums.size(); // the size of the array + this->n = the_sz / 2; // the number of operations to be done + + // initialize the array dp with -1, in other words mark as not calculated + memset(dp, -1, sizeof(dp)); + + + // return the answer to the problem + return rec(1, 0); + } +}; diff --git a/05- May/README.md b/05- May/README.md index c314c9784..0c09bf734 100644 --- a/05- May/README.md +++ b/05- May/README.md @@ -34,6 +34,7 @@ 1. **[Uncrossed Lines](#11--uncrossed-lines)** 1. **[Solving Questions With Brainpower](#12--solving-questions-with-brainpower)** 1. **[Count Ways To Build Good Strings](#13--count-ways-to-build-good-strings)** +1. **[Maximize Score After N Operations](#14--maximize-score-after-n-operations)**


@@ -727,4 +728,70 @@ public: } }; ``` + +
+

+ +## 14) [Maximize Score After N Operations](https://leetcode.com/problems/maximize-score-after-n-operations/) + +### Difficulty + +![](https://img.shields.io/badge/Hard-red?style=for-the-badge) + +### Related Topic + +`Array` `Math` `Dynamic Programming` `Backtracking` `Bit Manipulation` `Number Theory` `Bitmask` + +### Code + + +```cpp +class Solution { +public: + + // declare variables + int n, full_mask; + // vectors to store numbers and dynamic programming results + vector nums, dp; + + // function to check if a bit is empty in a binary mask + bool is_empty_bit(int bit, int mask){ + return !(mask & (1 << bit)); + } + + // recursive function to calculate the maximum score + int max_score(int mask){ + // if all bits are filled, return 0 + if(mask == full_mask) return 0; + // use memoization to avoid redundant computations + int& ret = dp[mask]; + // calculate the current index based on the number of filled bits + int idx = __builtin_popcount(mask) / 2 + 1; + // if the result has already been calculated, return it + if(~ret) return ret; + ret = 0; + // iterate over all pairs of numbers + for(int i = 0; i < n; i++) + for(int j = i + 1; j < n; j++) + // if both numbers are empty, calculate the score + if(is_empty_bit(i, mask) && is_empty_bit(j, mask)) + ret = max(ret, (idx * __gcd(nums[i], nums[j])) + max_score(mask | (1 << i) | (1 << j))); + // return the maximum score + return ret; + } + + int maxScore(vector& nums) { + // set the number of elements + n = nums.size(); + // set the vector of numbers + this -> nums = nums; + // set the full binary mask + full_mask = (1 << n) - 1; + // initialize the dynamic programming vector with -1 + dp = vector(1 << n, -1); + // return the maximum score starting with an empty mask + return max_score(0); + } +}; +``` \ No newline at end of file