How to solve M queens when M<N using backtracking approach - algorithm

This is the N queens problem. I know the N queens problem and its solution and I wrote a code in C++ programming language using backtracking approach:
#include <iostream>
using namespace std;
int col[100];
int n;
int m;
bool check(int i,int k){
for(int j=1 ; j<k ; j++){
if(col[j] == i || i-k == col[j] - j || i+k == col[j]+j)return false;
}
return true;
}
void queens(int k){
for(int i=1 ; i<=n ; i++){
if(check(i,k)){
col[k] = i;
if(k == n){
for(int j=1 ; j<=n ; j++)cout<<col[j]<<" ";
cout<<endl;
}
else queens(k+1);
}
}
}
int main(){
n = 4;
queens(1);
}
But here is my question if we have m queens instead of n which m < n how can I solve this question with backtracking approach I think a few changes in my code would solve the problem but I'm not sure of it.
I googled it but found nothing so is there any backtrack solution for this problem?

The answer is way more easier than you think! In regular N-queen problem, we iterate k, n times. So we can add our first queen at any place in the first column (between 1 till 8) and so on for other queens.
But if the queen count (m) is smaller than our chess size (n) we have to place that queen (our first queen) not only on the first column but everywhere (from 1 till 64) and do the same thing for other queens.
So the only thing you have to do is to iterate k, n*n times instead of n times.

You could make the function queens to have 2 parameters:
Column index you have currently reached (num_column)
Number of queens placed on the table (num_queens)
Now you must fix a column between [num_column, n] to place the queen.
Let (i, j) be the i'th row and j'th column (1 <= i <= n and num_column <= j <= n).
for j from num_column to n:
for i from 1 to n:
if check(i, j):
col[j] = i
queens(j + 1, num_queens + 1)
//resetting the queen on j'th column
col[j] = 0
You can stop the function when you reached num_queens == m.

Related

Given a matrix which only contains 0 and 1, and each row of the matrix is sorted, please find which row contains the most 1s

Given a matrix which only contains 0 and 1, and each row of the matrix is sorted, please find which row contains the most 1s. For a M*N matrix, O(M+N) time complexity is required, and O(1) space complexity is required.
Example
Input:
000000011111
000011111111
000000111111
000000000111
000000011111
000011111111
Output:
As row 2 and row 6 both contain 8 1s, the output is [2,8],[6,8].
I came up a solution:
public List<List<Integer>> mostOnes(int[][] a) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
for (int j = 0; j < a[0].length; j++) {
for (int i = 0; i < a.length; i++) {
if (a[i][j] == 1) {
List<Integer> res = new ArrayList<>();
res.add(i + 1);
res.add(a[0].length - j);
result.add(res);
}
}
if (result.size() != 0) break;
}
return result;
}
However, it is not O(M+N). Does anyone have other solutions?
The solution goes as follows:
Q= 0
For every row,
Search the next Q backward, starting from N - Q
Set the new Q there.
This process stops with Q indicating the largest number of 1's.
As the searches are performed by decreasing indexes from N down to 0 (at worst), and this is split between the M rows, the complexity is O(N + M). The trick is to continue the search from one row to the next staying in the current column rather than restarting from the edge.
Q= 0
for j in range(M):
for i in range(Q):
if A[j][N - 1 - i] == '0':
break
(Not guaranteed to be exact in details, but the working principle is there.)
0000000|11111
0000|11111111
0000|00111111
0000|00000111
0000|00011111
0000|11111111
Please check my O(m + n) implementation. The code is written in C, but easily you can convert it to Java.
int FindRow(vector<vector<int>>& mat) {
int m = mat.size(), n = mat[0].size();
int i = 0, j = n - 1, mx = 0;
while (i < m && j >= 0) {
while (j >= 0 && mat[i][j] == 1) --j;
mx = max(mx, n - j - 1);
++i;
}
return mx;
}
I have started with first row and last column. When I get first 0, I move to next row. We should check only remaining columns at most.

What is maximum water colledted between two histograms?

I recently came across this problem:
You are given height of n histograms each of width 1. You have to choose any two histograms such that if it starts raining and all other histograms(except the two you have selected) are removed, then the water collected between the two histograms is maximised.
Input:
9
3 2 5 9 7 8 1 4 6
Output:
25
Between third and last histogram.
This is a variant of Trapping rain water problem.
I tried two solutions but both had worst case complexity of N^2. How can we optimise further.
Sol1: Brute force for every pair.
int maxWaterCollected(vector<int> hist, int n) {
int ans = 0;
for (int i= 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
ans = max(ans, min(hist[i], hist[j]) * (j - i - 1));
}
}
return ans;
}
Sol2: Keep a sequence of histograms in increasing order of height. For every histogram, find its best histogram in this sequence. now, if all histograms are in increasing order then this solution also becomes N^2.
int maxWaterCollected(vector<int> hist, int n) {
vector< pair<int, int> > increasingSeq(1, make_pair(hist[0], 0)); // initialised with 1st element.
int ans = 0;
for (int i = 1; i < n; i++) {
// compute best result from current increasing sequence
for (int j = 0; j < increasingSeq.size(); j++) {
ans = max(ans, min(hist[i], increasingSeq[j].first) * (i - increasingSeq[j].second - 1));
}
// add this histogram to sequence
if (hist[i] > increasingSeq.back().first) {
increasingSeq.push_back(make_pair(hist[i], i));
}
}
return ans;
}
Use 2 iterators, one from begin() and one from end() - 1.
until the 2 iterator are equal:
Compare current result with the max, and keep the max
Move the iterator with smaller value (begin -> end or end -> begin)
Complexity: O(n).
Jarod42 has the right idea, but it's unclear from his terse post why his algorithm, described below in Python, is correct:
def candidates(hist):
l = 0
r = len(hist) - 1
while l < r:
yield (r - l - 1) * min(hist[l], hist[r])
if hist[l] <= hist[r]:
l += 1
else:
r -= 1
def maxwater(hist):
return max(candidates(hist))
The proof of correctness is by induction: the optimal solution either (1) belongs to the candidates yielded so far or (2) chooses histograms inside [l, r]. The base case is simple, because all histograms are inside [0, len(hist) - 1].
Inductively, suppose that we're about to advance either l or r. These cases are symmetric, so let's assume that we're about to advance l. We know that hist[l] <= hist[r], so the value is (r - l - 1) * hist[l]. Given any other right endpoint r1 < r, the value is (r1 - l - 1) * min(hist[l], hist[r1]), which is less because r - l - 1 > r1 - l - 1 and hist[l] >= min(hist[l], hist[r1]). We can rule out all of these solutions as suboptimal, so it's safe to advance l.

Construct any bipartite graph with degree constraints

We need to construct a bipartite graph with N vertices each, on the two parts, and with total number of edges equal to M.
The vertices on the left are numbered from 1 to N.
The vertices on the right are also numbered from 1 to N.
The degree of every vertex to be greater than or equal to X, and to be lesser than or equal to Y. i.e. for all v, X ≤ deg(v) ≤ Y
Given four integers N, M, X, Y we need to construct some bipartite graph satisfying this property. If there does not exist any such graph, then also tell the same.
Example :
If N=2 , M=3 , X=1 and Y=2
then the 3 edges in bipartite graph will be : (1,1),(2,2) and (1,2)
If N=2 , M=3 , X=1 and Y=1 then no bipartite graph exists.
How can this problem be solved if
1 ≤ N ≤ 100
1 ≤ X ≤ Y ≤ N
0 ≤ M ≤ N * N
Original question link
Obviously, the variables need to satisfy:
X * N <= M <= Y * N
Otherwise, there will be no solution.
Finding the edges could be done in waves. Start by connecting each node i from the first set to the according node i from the second set. In the next wave, connect i with (i + 1) mod N. Then i with (i + 2) mod N and so one. This will increase the degree of each vertex by exactly one in each wave. Stop whenever you have constructed M edges. This may also happen during a wave.
ACM ICPC 2016 India Preliminary Round Problem.
Link
The contest is now ended. I couldn't submit the answer (was about to submit the code just 10 secs before the end and my Internet stopped working).
d is equivalent to X in the OP's version of the problem.
D is equivalent to Y in the OP's version of the problem.
t is the number of test cases.
I made the code as per the original question in the link.
The logic is similar to
Nico Schertler's one. My complexity will be a little more because instead of just connecting, i+xth node to i in the xth iteration, I have used a set that finds the first element not connected in the range [1..N] and connects them.
This is my code:
#include <bits/stdc++.h>
using namespace std;
int main() {
int t, n, m, d, D;
cin >> t;
while(t--) {
cin >> n >> m >> d >> D;
if(n*D < m || n*d > m)
printf("-1\n");
else {
vector <set <int> > v(n);
int edges = 0, count = 0;
while(count != d) {
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if(v[i].find(j) == v[i].end()) {
v[i].insert(j);
++edges;
break;
}
if(edges == m)
break;
}
if(edges == m)
break;
}
++count;
}
while(edges < m) {
for(int i = 0; i < n; i++) {
if(v[i].size() == D)
continue;
for(int j = 0; j < n; j++) {
if(v[i].find(j) == v[i].end()) {
v[i].insert(j);
++edges;
break;
}
if(edges == m)
break;
}
if(edges == m)
break;
}
}
for(int i = 0; i < n; i++) {
set <int>::iterator it = v[i].begin();
for(; it != v[i].end(); ++it) {
printf("%d %d\n", i+1, (*it)+1);
}
}
}
}
return 0;
}
I don't know whether this code is correct or not.

How can I develop the exact recurrence for this?

N buildings are built in a row, numbered 1 to N from left to right.
Spiderman is on buildings number 1, and want to reach building number N.
He can jump from building number i to building number j iff i < j and j-i is a power of 2 (1,2,4, so on).
Such a move costs him energy |Height[j]-Height[i]|, where Height[i] is the height of the ith building.
Find the minimum energy using which he can reach building N?
Input:
First line contains N, number of buildings.
Next line contains N space-separated integers, denoting the array Height.
Output:
Print a single integer, the answer to the above problem.
So, I thought of something like this:
int calc(int arr[], int beg, int end, )
{
//int ans = INT_MIN;
if (beg == end)
return 0;
else if (beg > end)
return 0;
else
{
for (int i = beg+1; i <= end; i++ ) // Iterate over all possible combinations
{
int foo = arr[i] - arr[beg]; // Check if power of two or not
int k = log2(foo);
int z = pow(2,k);
if (z == foo) // Calculate the minimum value over multiple values
{
int temp = calc(arr,i,end);
if (temp < ans)
temp = ans;
}
}
}
}
The above is a question that I am trying to solve and here is the link: https://www.codechef.com/TCFS15P/problems/SPIDY2
However, the above recurrence is not exactly correct. Do I have to pass in the value of answer too in this?
We can reach nth building from any of (n-2^0),(n-2^1),(n-2^2)... buildings. So we need to process the buildings starting from 1. For each building i we calculate cost for getting there from any of earlier building j where i-j is power of 2 and take the minimum cost.
int calc(int arr[],int dp[],int n) {
// n is the target building
for(int i=1; i<=n; i++) dp[i]=LLONG_MAX; //initialize to infinity
dp[1]=0; // no cost for starting building
for(int i=2; i<=n; i++) {
for(int j=1; i-j>=1; j*=2) {
dp[i]=min(dp[i], dp[i-j]+abs(arr[i]-arr[i-j]));
}
}
return dp[n];
}
Time complexity is O(n*log(n)).
First, you are doing the check for a power of 2 on the wrong quantity. The jumps have to be between buildings that are separated in index by a power of 2, not that differ in height (which is what you are checking).
Second, the recursion should be formulated in terms of the cost of the first jump and the cost of the remaining jumps (obtained by a recursive call). You are looking for the minimum cost over all legal first jumps. A first jump is legal if it is to a building that is at an index less than N and also a power of 2 in index away from the current start.
Something like this should work:
int calc(int arr[], int beg, int end)
{
if (beg == end)
return 0;
else if (beg > end)
throw an exception
int minEnergy = INFINITY;
for (int i = 1; // start with a step of 1
beg + i <= end; // test if we'd go too far
i <<= 1) // increase step to next power of 2
{
int energy = abs(arr[beg + i] - arr[beg]) // energy of first jump
+ calc(arr, beg + i, end); // remaining jumps
if (energy < minEnergy) {
minEnergy = energy;
}
}
return minEnergy;
}
The efficiency of this search can be greatly improved by passing the minimum energy obtained so far. Then if abs(arr[beg + i] - arr[beg]) is not less than that quantity, there's no need to do the recursive call, because whatever is found will never be smaller. (In fact, you can cut off the recursion if abs(arr[beg + i] - arr[beg]) + abs(arr[end] - arr[beg + i]) is not smaller than the best solution so far, because Spiderman will have to at least spend abs(arr[end] - arr[beg + i]) after getting to building beg + i.) Adding this improvement is left as an exercise. :)

Implementing quickselect

I'm trying to implement the quickselect algorithm. Though, I have understood the theory behind it very well; I'm finding it difficult to convert it into a well functioning program.
Here is how I'm going step by step to implement it and where I am facing problem:
Problem: Find the 4th smallest element in A[] = {2,1,3,7,5,4,6}
k = 4.
index:0|1|2|3|4|5|6
Corresponding values: 2|1|3|7|5|4|6
initially, l = 0 and r = 6
Step 1) Taking pivot as the leftmost element (pivot will always be the leftmost in this problem)-
pivot_index = 0
pivot_value = 2
Step 2) Applying the partition algo; putting the pivot at the right place ([<p][p][>p])-
We get the following array: 1|2|3|7|5|4|6
where, pivot_index = i-1 = 1
and therefore, pivot_value = 2
Step 3) Compare pivot_index with k-
k=3, pivot_index = 1; k>pivot_index
Hence, Our k-th smallest number lies in the right part of the array.
Right array = i to r and we do not bother with the left part (l to i-1) anymore.
Step 4) We modify the value of k as k - (pivot_index) => 4-1 = 2; k = 3.
Here is the problem: Should not the value of k be 2? Because we have two values on the left part of the array: 1|2? Should we calculate k as k - (pivot_index+1)?
Let's assume k = 3 is correct.
Step 5) "New" array to work on: 3|7|5|4|6 with corresponding indexes: 2|3|4|5|6
Now, pivot_index = 2 and pivot_index = 3
Step 6) Applying partition algo on the above array-
3|7|5|4|6 (array remains unchanged as pivot itself is the lowest value).
i = 3
pivot_index = i-1 = 2
pivot_value = 3
Step 7) Compare pivot_index with k
k=3 and pivot_index=2
k > pivot_index
and so on....
Is this approach correct?
Here is my code which is not working. I have used a random number generator to select a random pivot, the pivot is then swapped with the first element in the array.
#include<stdio.h>
#include<stdlib.h>
void print_array(int arr[], int array_length){
int i;
for(i=0; i<array_length; ++i) {
printf("%d ", arr[i]);
}
}
int random_no(min, max){
int diff = max-min;
return (int) (((double)(diff+1)/RAND_MAX) * rand() + min);
}
void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int get_kth_small(int arr[], int k, int l, int r){
if((r-l) >= 1){
k = k + (l-1);
int pivot_index = random_no(l, r);
int i, j;
swap(&arr[pivot_index], &arr[l]); //Switch the pivot with the first element in the array. Now, the pivit is in arr[l]
i=l+1;
for(j=l+1; j<=r; ++j){
if(arr[j]<arr[l]){
swap(&arr[j], &arr[i]);
++i;
}
}
swap(&arr[l], &arr[i-1]); //Switch the pivot to the correct place; <p, p, >p
printf("value of i-1: %d\n", i-1);
printf("Value of k: %d\n", k);
if(k == (i-1)){
printf("Found: %d\n", arr[i]);
return 0;
}
if(k>(i-1)){
k=k-(i-1);
get_kth_small(arr, k, i, r);
} else {
get_kth_small(arr, k, l, r-1);
}
//get_kth_small(arr, k, i, r);
//get_kth_small(arr, k, l, i-1);
}
}
void main(){
srand(time(NULL));
int arr[] = {2,1,3,7,5,4,6};
int arr_size = sizeof(arr)/sizeof(arr[0]);
int k = 3, l = 0;
int r = arr_size - 1;
//printf("Enter the value of k: ");
//scanf("%d", &k);
get_kth_small(arr, k, l, r);
print_array(arr, arr_size);
printf("\n");
}
What you describe is a valid way to implement quick select. There are numerous other approaches how to select the pivot and most of them will give a better expected complexity but in essence the algorithm is the same.
"Step 2: putting the pivot at the right place": don't do that. In fact you can't put the pivot at the right place, as you don't know what it is. The partitioning rule is to put all elements smaller or equal than the pivot before those larger. Just leave the pivot where it is!
Quick select goes as follows: to find the Kth among N elements, 1) choose a pivot value, 2) move all elements smaller or equal to the pivot before the others, forming two zones of length Nle and Ngt, 3) recurse on the relevant zone with (K, Nle) or (K-Nle, Ngt), until N=1.
Actually, any value can be taken for the pivot, even one not present in the array; but the partition must be such that Nle and Ngt are nonzero.

Resources