I need to solve a maze using backtracking method.
My maze has 0 listed as a wall, 1 listed as an empty cell, 2 is for visited, 3 for dragon.
Dragons are basically obstacles that I can go through BUT I need to choose the path with the LEAST dragons.
So far I can solve the maze and mark a path, but I can't seem to think of a relatively simple way of finding the path with the least dragons.
Do note we just started coding with C in my uni (so far I've only done java/bash/a bit of python), so I'm really new to C and algorithms in general.
Code is below.
#include <stdio.h>
#define IMPOSSIBLE (N*N+1)
int counter=0;
enum {WALL,EMPTY,VISITED,DRAGON,N};
int printMaze(int maze[N][N])
{
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
printf("%d ",maze[i][j]);
}
printf("\n");
}
}
int solveMaze(int maze[N][N], int i, int j)
{
if (maze[i][j] == WALL){ return 0; } // If [i][j] are currently a wall (0).
if (maze[i][j] == VISITED) { return 0; } // If [i][j] are currently a mark (2).
if (maze[i][j] == DRAGON) { counter++; }
maze[i][j] = VISITED; // Mark current spot with (2).
if (i==N-1 && j==N-1) { return 1; } // reached the end (N-1,N-1) - (3,3) incase N is 4.
if ( ((i < N-1) && solveMaze(maze,i+1,j)) || ((i > 0) && solveMaze(maze,i-1,j)) || ((j < N-1) && solveMaze(maze,i,j+1)) || ((j > 0) && solveMaze(maze,i,j-1)) ) { // checking index-out-bounds + recursively going around the maze
return 1;
}
maze[i][j] = EMPTY;
return 0;
}
int main() {
int maze[N][N] = { {1,1,3,3},
{3,0,1,1},
{3,0,0,1},
{1,3,3,1} };
int solved = solveMaze(maze, 0, 0);
if (solved)
{
printMaze(maze);
printf("Amount of dragons passed through in the maze: %d\n",counter);
}
else
{
printf("No solution, %d\n",IMPOSSIBLE);
}
}
I tried creating a counter that counts the amount of dragons on the way, but I guess I'm not fluent enough in recursions to make it go in every available path and choose the best one.
You seem to understand the idea of recursively traversing the tree with backtracking. The issue is that you need to find not just a path, but the one with the least cost -- that is, the fewest dragons. That means that in general, you can't stop with the first path you find. You need to keep going until you can be sure that there's no better path.
Here's one way to do it:
Maintain a variable to track the number of dragons along the best path discovered so far. Initialize it to something larger than the value that can appear along any path -- your IMPOSSIBLE, for example, or INT_MAX. This is separate from the number of dragons so far encountered along the path you are currently exploring.
Perform a recursive traversal much like you are already doing, except
Fix the example code's problems with restoring state (node contents and counter value) when you backtrack out of a dragon node.
Stop exploring any given path when the number of dragons encountered along it equals the number along the best path discovered so far.
In light of the previous, you can be certain that whenever you discover a path that reaches the exit, that path has fewer dragons than the best path previously discovered, if any. Update the variable tracking the best number of dragons accordingly. Note that this does not necessarily end the search, but it may reduce the search space that remains to be explored.
A way to solve this is to imagine the maze as a 3 dimensional graph instead of 2D. You have the triplet (i, j, number_of_dragons) define the nodes of the graph. Note that this may in extreme case mean the number of nodes are N^4. Thus you will need an array with size [N][N][N*N] to store if the given node is visited (note that dragons and walls can still be stored in a [N][N] array). To get the minimal path from source to target, simply iterate over the the values of [target.x][target.y][i] and return the minimum i for which you have visited the node.
I can suggest a better solution using min path graph algorithm like Dijkstra, but it seems this is out of scope for the question.
Related
[My apology for the title, I just specified the problem I encountered on this puzzle.
I'm making a path finding method with the least distance travelled, depending on the number of asterisks encountered.
The rules of the game is simple, traversing from A to B, but I can only move in a straight line and cannot stop moving in that direction until you hit an asterisk (or the B), as if they were sliding across every zero.
Example, the photo shows the shortest path from A to B with 23 as the total distance travelled.
]1
The first idea that appeared on my mind is making an adjacency matrix, initially, which I have my code here:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
int main()
{
FILE *hehehe = fopen("input.txt","r");
//==========================ADJACENCY MATRIX INITIALIZATION=======================================//
int row, column, i, j;
fscanf(hehehe,"%d",&row);
fscanf(hehehe,"%d",&column);
char c;
c = fgetc(hehehe);
int matrix[row][column];
c = fgetc(hehehe);
for (i = 0; i < row; i++)
{
for (j = 0; j < column; j++)
{
if (c == '*'){
matrix[i][j] = 1;
c = fgetc(hehehe);
}
else if (c == 'A')
{
matrix[i][j] = 2;
c = fgetc(hehehe);
}
else if (c == 'B')
{
matrix[i][j] = 3;
c = fgetc(hehehe);
}
else{
matrix[i][j] = 0;
c = fgetc(hehehe);
}
if (c == '\n'){c = fgetc(hehehe);}
}
}
for (i = 0; i < row; i++)
{
for (j = 0; j < column; j++)
{
//if (matrix[i][j] == 1) printf("*");
//else printf(" ");
printf("%d ",matrix[i][j]);
}
printf("\n");
}
fclose(hehehe);
}
Any idea or suggestion for continuing for making of edge in every straight line in the photo is high appreciated. Thank you for any help in advance.
In this case, I think a matrix is overdoing it. Because you cannot make a move while sliding, you only need a directed graph.
There are a few things to keep in mind while making your algorithm:
Stopping points are the goal, or any space adjacent to a wall/asterisk.
A vertex should store two values; direction, and location.
For each asterisk or obstacle, add adjacent spaces to the list of vertices (if they don't exist in your graph yet). They only require one direction.
For each B, add a vertex with all possible directions. (Or one vertex for each direction, depending on whether that makes it easier).
For each vertex, find the closest vertex in the direction stored. Draw an edge between both vertices (if it does not already exist).
Run an appropriate search algorithm. If distance matters, use Dijkstra's. If it doesn't, use Breadth-first. If there are special scoring rules, consider A*.
Because your search space doesn't seem so large, I haven't fully optimized the algorithm. This is why I mention checking that vertices and edges aren't already added. Optimizing these is possible, and I can help with that if you need, but if-statements aren't costly enough to warrant premature optimization. Because your search space is easy to simplify, Breadth-first and Dijkstra's algorithm are absolutely perfect; they find the shortest path and their performance cost is nowhere near as high as putting them on a 2D grid.
If you're not sure of how to make your data structures, here's the way I'd approach it.
1.
Graph Structures
Direction // x and y tuple/variable, integer, or string
Point // x and y tuple/variable. Note that you can use this as direction too
Vertex
- Point
- Map < Direction, Edge > // each direction is linked to another vertex
// maps in C can be made with two arrays
// a vertex for each direction may be easier
Edge
- Vertex // you can store both vertices, but you only need to store the one being moved to.
// without OOP, reuse a simple struct before making it complex
Graph
- Vertices // array of vertex
// each vertex stores its edges; the graph doesn't need to
2.
Pathfinder Structures
Node
- Parent // a link to the previous node
// trace the links back to construct a path
- Depth // last node's depth + 1
- Vertex // the vertex hit by the pathfinder
Path
- Nodes // while parent is not null
// add a node to this list
// then read it backward
I am doing an algorithm exercise, which asks to rearrange an array of integers, to put all the even-valued elements before odd-valued elements.
I thought for a while and came up with the following pseudo code:
int[] Rearrange(int [] arr)
{
if arr.length=1
return arr;
if arr[0] is even
return arr[0] followed by Rearrange(arr.subarray(1,arr.length))
else
return Rearrange(arr.subarray(1,arr.length)) followed by arr[0]
}
I am bit concerned about my proposed solution above, since I need to do a copy operation in each recursion cycle, which is expensive. Experts please kindly advise, thanks!
Recursion is expensive, and your approach would create tons of extra copies. Sometimes recursion yields an elegant solution, and other times it is absolutely the wrong tools for the job. This is a wrong-tool-for-the job case.
Instead, write a method that keeps a head index and a tail index. Initialize the head pointer to the beginning of the array and the tail index to the end.
At each pass, loop through the items at the head of the list, looking for odd values. When you find one, stop, then look for an even value from the end, looking backwards. When you find one, switch the two values (using a third int as temporary storage.) Repeat forever. When the head and tail indexes meet, you're done.
Something like this:
int head_index = 0;
int tail_index = array.count;
int temp;
while (true)
{
//Find the next odd number at the front of the array.
while (array[head_index] %2==0) && head_index < tail_index)
head_index++;
//Find the next even number at the end of the array.
while (array[tail_index]%2==1 && head_index < tail_index)
tail_index--;
//If the pointers meet, we're done
if (head_index <= tail_index)
break;
//Swap the items at the current indexes
temp = array[head_index];
array[head_index] = array[tail_index];
array[tail_index] = temp;
}
(Completely untested, and I'm tired, but the basic idea should work)
It's more-or-less C syntax pseudo code.
It should run in O(n) time, with the only extra RAM needed being your 2 indexes and the temporary holding variable.
Even though the question was answered, I'm putting the recursive version of solving this problem here so that people, who are wondering, can see why recursion is a bad approach for this problem.
public static int[] segregate(int[] array, int left) {
int leftIndex = left;
if(left == array.length) {
return array;
}
for(int i = leftIndex + 1; i < array.length; i++) {
if(array[leftIndex] % 2 == 1) {
if(array[i] % 2 == 0) {
int temp = array[leftIndex];
array[leftIndex] = array[i];
array[i] = temp;
}
}
}
return segregate(array, leftIndex + 1);
}
As can be seen from the code, the method will call itself N times. When you consider the fact that the complexity of for loop in the method is O(N), the total complexity of recursion will be O(n*2) which is worse than non-recursive solution.
I can solve an easy puzzle but attempting a slightly harder one is impossible; what am I overlooking? Here is my solver method:
int solver (int x, int y)
{
int a, b, i, j;
for (a=1; a<10; a++)
{
if (checkEverything(x, y, a))
{
board[x][y] = a;
counter++;
if (counter == 81)
{
return true;
}
if (x == 9)
{
return true;
}
if (counter > 200 || counter < -10) {
return false;
}
for (i=0; i<9; i++)
{
for (j=0; j<9; j++)
{
if (board[i][j] == 0)
{
if (solver(i, j))
{
return true;
}
}
}
}
counter--;
}
}
board[x][y] = 0;
return false;
}
My checkEverything function checks to make sure that the given number is safe to be placed in the row, column, and 3x3 grid...I am very lost because it seems to be right to me but it is so slow. Thanks for any help!
Your implementation takes too much extra checking.
When finding a current valid candidate for current (x, y), it is redundant to find the next undetermined position from the beginning of the chessboard.
The complexity for your recursive function will be O(N*N)*O(N)*M(N is the side length of the chessboard, or 9. M is the complexity of your checkEverything ).In this expression, O(N*N) is to find the next undetermined position and O(N) is the complexity of try every digit from 1 to N. I don't know how you implement checkEverything, but a naive implement will be M = O(N). That means the total complexity may be about O(N4)
The common advices for optimization will be:
reduce the complexity of finding the next position to be O(1). You can preprocess the chessboard and obtain all of the undetermined positions into an list in advance.
reduce the complexity of checkEverything. It can be reduced into O(1) by using some hash tables to hold digits already used, 9 for the each column, 9 for each row, 9 for each sub rectangle.
With this two advice, the complexity of the recursive will be O(N).
If you want a perfect performance, I advice you to learn Dancing Links invented by Knuth. The main idea of this algorithm is using a 2 dimension double linked list to store all candidate of all positions and accelerate finding the next position and the next candidate, delete invalid candidates and recover when backtracing.
http://en.wikipedia.org/wiki/Dancing_Links
I am trying my best to get this code done. It's been well over 15 hours now at least over the course of a couple days, and I am still stuck. I am programming in C, and it is my first language, so I am a bit of a noob I'm sorry. Any kind of help would be very helpful.
A quick first question:
while (manStatus[i] == -1 || womanStatus[i] == -1)
What would be the proper syntax or way to say that I want to continuously check the elements of my array to see if any value inside there is "-1" (or in reality, that the men and women inside those arrays are single, so keep attempting to pair them).
I have more, but this one has stumped me for days. I'll keep struggling with the rest, but would love some help with this for starters if anyone has a moment.
In C one cannot simply expect manStatus[i] == -1 to check all the values within the array and return true if any value within matches -1.
Rather you need to write an algorithm which manually does the meticulous checking of each element in the array. It's actually very simple and uses a loop. I've implemented it here as a function:
bool checkArray(int array[],int arrayLength, int val)
{
int i;
for(i = 0; i < arrayLength; i++)
{
if(array[i] == val)
return true;
}
return false;
}
Now you can call this function in your statement:
while (checkArray(manStatus, LENGTH_OF_ARRAY, -1) || checkArray(womenStatus, LENGTH_OF_ARRAY, -1))
Well, there is lsearch that could be handy, but that is a non-standard function.
Define a helper function to check if a value is in an array.
int containsInt(int *array, size_t length, int value) {
size_t i;
for(i = 0; i < length; i++) {
if(array[i] == value) {
return 1;
}
}
return 0;
}
Then your check becomes,
while(!containsInt(manStatus, numMen, -1) && !containsInt(womanStatus, numWomen, -1))
If you want to check that any value in manStatus array is -1 you can do like this:
#define NON_WITH_MINUS_ONE 0
#define SOME_WITH_MINUS_ONE 1
int checkMarriage(int *manStatus,int N)
{
for(i=0;i<N;i++)
if(manStatus[i]==-1)
return SOME_WITH_MINUS_ONE
return NON_WITH_MINUS_ONE
}
where N is number of elements in the array. Then you can call this function e.g. by
if(checkMarriage(manStatus, 20)==1)
{//do something}
else
{ //do something else}
With the way you have done it, if you run out of either men or women before the other array has run out, then you are stuck in an infinite loop.
The best way to break out of the loop once there can be no more matches is:
while (manStatus[i] == -1` && `womanStatus[i] == -1)
Let me first answer on a math point of view. From my understanding, you have two finite sets (happily the number of human beings on earth is finite ... Hugh). The first one, which I will denote Sw is the set of women (ladies first guys !). The second is the men's one : Sm.
Now, you want to pair women from Sw with men from Sm. The cardinal number of each set is not guaranteed to be the same. I will denote them i = |Si|, where i ∈ {w, m}.
Suppose we have w > m (heh heh), then all you have to do is to choose a subset Sw,m of m women amongst the w that are in Sw (there are w! / ((w - m)!.m!) such subsets) and then set up a bijection between Sm and Sw,m. There are m! such bijections. Then you extend the bijection by setting the other women to the single status (which is -1 if I got it right).
From now on, you have two possibilities :
Generate one such "extended bijection" p and bind man i with women p(i) (the leftover poor little women to status -1).
You are given the two sets partially "paired" and you want to pair remaining singles as much as possible.
Before I go further, can you tell me which approach is the one that interests you ?
I found this question on a programming forum:
A table composed of N*M cells,each having a certain quantity of apples, is given. you start from the upper-left corner. At each step you can go down or right one cell.Design an algorithm to find the maximum number of apples you can collect ,if you are moving from upper-left corner to bottom-right corner.
I have thought of three different complexities[in terms of time & space]:
Approach 1[quickest]:
for(j=1,i=0;j<column;j++)
apple[i][j]=apple[i][j-1]+apple[i][j];
for(i=1,j=0;i<row;i++)
apple[i][j]=apple[i-1][j]+apple[i][j];
for(i=1;i<row;i++)
{
for(j=1;j<column;j++)
{
if(apple[i][j-1]>=apple[i-1][j])
apple[i][j]=apple[i][j]+apple[i][j-1];
else
apple[i][j]=apple[i][j]+apple[i-1][j];
}
}
printf("\n maximum apple u can pick=%d",apple[row-1][column-1]);
Approach 2:
result is the temporary array having all slots initially 0.
int getMax(int i, int j)
{
if( (i<ROW) && (j<COL) )
{
if( result[i][j] != 0 )
return result[i][j];
else
{
int right = getMax(i, j+1);
int down = getMax(i+1, j);
result[i][j] = ( (right>down) ? right : down )+apples[i][j];
return result[i][j];
}
}
else
return 0;
}
Approach 3[least space used]:
It doesn't use any temporary array.
int getMax(int i, int j)
{
if( (i<M) && (j<N) )
{
int right = getMax(i, j+1);
int down = getMax(i+1, j);
return apples[i][j]+(right>down?right:down);
}
else
return 0;
}
I want to know which is the best way to solve this problem?
There's little difference between approaches 1 and 2, approach 1 is probably a wee bit better since it doesn't need the stack for the recursion that approach 2 uses since that goes backwards.
Approach 3 has exponential time complexity, thus it is much worse than the other two which have complexitx O(rows*columns).
You can make a variant of approach 1 that proceeds along a diagonal to use only O(max{rows,columns}) additional space.
in term of time the solution 1 is the best because there is no recursie function.
the call of recursive function takes time
Improvement to First Approach
Do you really need the temporary array to be N by M?
No.
If the initial 2-d array has N columns, and M rows, we can solve this with a 1-d array of length M.
Method
In your first approach you save all of the subtotals as you go, but you really only need to know the apple-value of the cell to the left and above when you move to the next column. Once you have determined that, you don't look at those previous cells ever again.
The solution then is to write-over the old values when you start on the next column over.
The code will look like the following (I'm not actually a C programmer, so bear with me):
The Code
int getMax()
{
//apple[][] is the original apple array
//N is # of columns of apple[][]
//M is # of rows of apple[][]
//temp[] is initialized to zeroes, and has length M
for (int currentCol = 0; currentCol < N; currentCol++)
{
temp[0] += apple[currentCol][0]; //Nothing above top row
for (int i = 1; i < M; i++)
{
int applesToLeft = temp[i];
int applesAbove = temp[i-1];
if (applesToLeft > applesAbove)
{
temp[i] = applesToLeft + apple[currentCol][i];
}
else
{
temp[i] = applesAbove + apple[currentCol][i];
}
}
}
return temp[M - 1];
}
Note: there isn't any reason to actually store the values of applesToLeft and applesAbove into local variables, and feel free to use the ? : syntax for the assignment.
Also, if there are less columns than rows, you should rotate this so the 1-d array is the shorter length.
Doing it this way is a direct improvement over your first approach, as it saves memory, and plus iterating over the same 1-d array really helps with caching.
I can only think of one reason to use a different approach:
Multi-Threading
To gain the benefits of multi-threading for this problem, your 2nd approach is just about right.
In your second approach you use a memo to store the intermediate results.
If you make your memo thread-safe (by locking or using a lock-free hash-set) , then you can start multiple threads all trying to get the answer for the bottom-right corner.
[// Edit: actually since assigning ints into an array is an atomic operation, I don't think you would need to lock at all ].
Make each call to getMax choose randomly whether to do the left getMax or above getMax first.
This means that each thread works on a different part of the problem and since there is the memo, it won't repeat work a different thread has already done.