Given a roadmap between a number of cities, with roads between 2 cities containing tunnels, your goal is to find the shortest possible paths between the start city and all the other cities, such that each path contains at least one tunnel. (The problem doesn't always have a solution). Assume the cost of the roads is given. Input - from a file, output - to a file, containing the start city and the path to the rest of the cities.
Now I tried to do this with Dijkstra's algorithm, it solved most of my problem except the part where tunnels are mandatory. Can anyone help me with this? This is my code.
Thanks in advance!
File input:
10
1 2 10
1 4 5
2 3 1
2 4 3
3 5 6
4 2 2
4 3 9
4 5 2
5 1 7
5 3 4
#include <stdio.h>
#define GRAPHSIZE 2048
#define INFINITY GRAPHSIZE*GRAPHSIZE
#define MAX(a, b) ((a > b) ? (a) : (b))
int e; /* The number of nonzero edges in the graph */
int n; /* The number of nodes in the graph */
long dist[GRAPHSIZE][GRAPHSIZE];/* dist[i][j] is the distance between node i and j; or 0 if there is no direct connection */
long d[GRAPHSIZE]; /* d[i] is the length of the shortest path between the source (s) and node i */
int prev[GRAPHSIZE]; /* prev[i] is the node that comes right before i in the shortest path from the source to i*/
void printD() {
int i;
printf("Distances:\n");
for (i = 1; i <= n; ++i)
printf("%10d", i);
printf("\n");
for (i = 1; i <= n; ++i) {
printf("%10ld", d[i]);
}
printf("\n");
}
/*
* Prints the shortest path from the source to dest.
* dijkstra(int) MUST be run at least once BEFORE
* this is called
*/
void printPath(int dest) {
if (prev[dest] != -1)
printPath(prev[dest]);
printf("%d ", dest);
}
void dijkstra(int s) {
int i, k, mini;
int visited[GRAPHSIZE];
for (i = 1; i <= n; ++i) {
d[i] = INFINITY;
prev[i] = -1; /* no path has yet been found to i */
visited[i] = 0; /* the i-th element has not yet been visited */
}
d[s] = 0;
for (k = 1; k <= n; ++k) {
mini = -1;
for (i = 1; i <= n; ++i)
if (!visited[i] && ((mini == -1) || (d[i] < d[mini])))
mini = i;
visited[mini] = 1;
for (i = 1; i <= n; ++i)
if (dist[mini][i])
if (d[mini] + dist[mini][i] < d[i]) {
d[i] = d[mini] + dist[mini][i];
prev[i] = mini;
}
}
}
int main(int argc, char *argv[]) {
int i, j;
int u, v, w;
FILE *fin = fopen("dist.txt", "r");
/* the first line contains e, the number of edges the following e lines
contain 3 numbers: u, v and w signifying that there’s an edge from u to v of weight w*/
fscanf(fin, "%d", &e);
for (i = 0; i < e; ++i)
for (j = 0; j < e; ++j)
dist[i][j] = 0;
n = -1;
for (i = 0; i < e; ++i) {
fscanf(fin, "%d%d%d", &u, &v, &w);
dist[u][v] = w;
n = MAX(u, MAX(v, n));
}
fclose(fin);
dijkstra(1);
printD();
printf("\n");
for (i = 1; i <= n; ++i) {
printf("Path to %d: ", i);
printPath(i);
printf("\n");
}
return 0;
}
Run Dijkstra's algorithm to find all the shortest paths from the starting city to all tunnels.
The run Dijkstra's algorithm again with all the tunnels as starting points to find all the shortest paths to all the other cities. So you'll sort of start in the middle of Dijkstra's algorithm, where you already have a bunch of candidates (all the tunnels) in your priority queue, and all of these will be marked as visited.
It doesn't look like you're using a priority queue (the efficient implementation of Dijkstra's algorithm uses one), but I'm sure you'll manage to figure out how to apply my solution to your code nonetheless.
You can construct a graph like this: have two nodes per city (say C and C' for each city C). For each road, say from C1 to C2, add edges to the graph: C1->C2 and C1'->C2'. For each tunnel, say from C1 to C2, add edges to the graph C1->C2' and C1'->C2'.
The intuition is that to get to a C' node you have to go through at least one tunnel.
Now, to find the shortest path from C1 to C2 using at least one tunnel, simply use Dijkstra to find the shortest path from C1 to C2'. Or to find shortest paths to each city, find all shortest paths from the start city to C' for each city C.
Related
this question been asked a few times but cannot find anything specific, the topic is I'm trying to perform a merge sort using 2 threads for sorting each sub list, each thread taking a half, and a third thread to merge the two lists afterwards,
but I'm having difficulty, understanding the merge sort, (first time trying to write a sort algorithm in
c)
i know i need to lets say take "apart" the merge sort and perform only each half in two separate functions, that I can pass into the thread, then perform the final merging process, but lets say I have lists
list1 11 22 1 6 9
list2 99 33 4 5 7
I know I could write a simple sort algorithm to put each in order, but the merging process is throwing me for a loop soheres what im thinking or visualizing the error, and what i am lost on, say i sort the two lists with their different thread functions
list1 1 6 9 11 22
list2 4 5 7 33 99
I keep thinking this will be the result if I go ahead and merge them at this stage
1 6 9 11 22 4 5 7 33 99
that isn't exactly in order is it?
and if I sort them in the final merger using a sort, I mean what was the point of sorting them initially? that kind of just makes the point of sorting them in the two subthreads pointess, when my goal is to use the 2 threads and 2 threads only, then use the final thread to merge like a merge sort would sort each array
can anyone help me visualize this better, either with code, or pseudocode?, assume that in my code I already have the array split and ready to be passed into the functions in my main(void) function, with pointers named first_half, second_half, the starter array is constructed, by taking a user input and passing that into a malloc function, and filled using random limited to 0-99
The way merge sort is working is by comparing the sorted element of each list together, it does not concatenate one array after another, see example code below (singlethreaded):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define _DEBUG 1
void insertion_sort(int n, int a[n])
{
int i, tmp, j;
for (i = 1; i < n; i++) {
tmp = a[i];
j = i - 1;
while (j >= 0 && a[j] > tmp) {
a[j + 1] = a[j];
--j;
}
a[j + 1] = tmp;
}
#ifdef _DEBUG
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
putchar('\n');
#endif
}
void merge_sort(int n, int a[n], int x, int b[x], int y, int c[y])
{
for (int i = 0; i < x; i++) // split values of a into two arrays
b[i] = a[i];
for (int i = 0; i < y; i++)
c[i] = a[i+x];
insertion_sort(x, b); // sort each of the sub arrays, you multithread this part.
insertion_sort(y, c);
int i = 0;
int j = 0;
int k = 0;
while (i < n) {
if (b[j] < c[k]) // you add to a the smallest between b and c.
a[i++] = b[j++];
else
a[i++] = c[k++];
if (x == j) { // if all the elements of b have filled a:
do {
a[i++] = c[k++]; // we proceed to fill a with c
} while (y != k);
break ; // the merge sorting is completed.
}
else if (y == k) {
do {
a[i++] = b[j++];
} while (x != j);
break ;
}
}
#ifdef _DEBUG
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
putchar('\n');
#endif
}
int main(void) {
srand ( time(NULL) );
const int n = 100;
int a[n];
int b[n/2];
int c[(n+1)/2];
for (int i = 0; i < n; i++) // initialize with random values
a[i] = rand() % 1000;
merge_sort(n, a, n/2, b, (n+1)/2, c);
}
I am doing an assignment for class that is supposed to be coded a very specific way. Here is the goal:
Goal: To implement Dijkstra’s algorithm for single source shortest path problem
for a given directed graph using an adjacency matrix representation of the
graph.
I am using Makefile to compile the code. Input will be taken via the terminal/console ./a7 < datafile. Here is an example of the input:
6 11 0
0 1 50
0 2 10
0 4 45
1 2 15
1 4 10
2 0 20
2 3 15
3 1 20
3 4 35
4 3 30
5 4 03
And the expected output:
0 2 10
0 3 25
0 1 45
0 4 45
0 5 INF (no path)
Here is the code:
#include <limits.h> /* for INT_MAX */
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define N 10 /* max matrix size is 10 x 10 */
#define INF INT_MAX /* infinity? */
int main(int argc, char **argv) {
void getdata(int amtrx[][N], int *sz, int *stv);
void dijkstras(int amtrx[][N], int src);
if (argc < 2) {
printf("Missing Filename.\n");
return(1);
} else if (argc > 2) {
printf("Too many arguments.\n");
return(1);
}
FILE *f = fopen(argv[1], "r");
int amtrx[N][N], *sz, *stv;
stv = malloc(sizeof(int));
sz = malloc(sizeof(int));
getdata(amtrx, sz, stv);
dijkstras(amtrx, *stv);
fclose(f);
return(0);
}
void getdata(int amtrx[][N], int *sz, int *stv) {
int i, j, nsz, nedg, fr, to, vtx, wt;
scanf("%d %d %d", &nsz, &nedg, &vtx);
for(i = 0; i < nsz; i++)
for(j = 0; j < nsz; j++)
amtrx[i][j] = INF;
for(i = 0; i < nedg; i++) {
scanf("%d %d %d", &fr, &to, &wt);
amtrx[fr][to] = wt;
amtrx[to][fr] = wt;
}
*sz = nsz;
*stv = vtx;
}
void dijkstras(int amtrx[][N], int src) {
void printpaths(int amtrx[][N]);
int mindistance(int dist[], bool sptSet[]);
int dist[N];
bool sptSet[N];
int i, count, v, u;
for (i = 0; i < N; i++)
dist[i] = INF, sptSet[i] = false;
dist[src] = 0;
for (count = 0; count < N - 1; count++) {
u = mindistance(dist, sptSet);
sptSet[u] = true;
for (v = 0; v < N; v++)
if (!sptSet[v] && amtrx[u][v] && dist[u] != INF && dist[u] + amtrx[u][v] < dist[v]) {
dist[v] = dist[u] + amtrx[u][v];
}
}
printpaths(amtrx);
}
int mindistance(int dist[], bool sptSet[]) {
int min = INF, min_index;
int v;
for (v = 0; v < N; v++)
if (sptSet[v] == false && dist[v] <= min)
min = dist[v], min_index = v;
return min_index;
}
void printpaths(int amtrx[N][N]) {
//to be written
}
So far it just runs forever and doesn't print anything. I suspect maybe an infinite loop but I can't see where it's happening. I tried to run in GDB and it just says Starting program: /a7 datafile and goes no where. I also would like help making sure my algorithm is correct, but I can save that for another question if need be. Thanks in advance!
To find out what is wrong with help of gdb you usually need to run program in step mode to see where and why it hangs or loops.
Ensure that you compiled your program with debug symbols (if you are using gcc or similar compiler then -g option is needed).
To avoid going over whole program in step mode you can just hit Ctrl-C in gdb at the time you think your program hanged and then enter command bt. It will show you where your program is. You can then enter command cont, and break program execution after some time to see if you are in different place, or in the same...
If you still don't know what is the reason of your problem after step 2, you can kill program and set up break point before the place you have identified as being the one in which your program hangs/loops --- read gdb documentation about break to see how to set up breakpoint.
Here is link for gdb tutorial hosted at CMU: https://www.cs.cmu.edu/~gilpin/tutorial/
I am trying to implement the graph coloring algorithm in C, this implementation is based on how we assign the colors by iterating through the adjacency matrix. I am unable to get it after assigning a color to the second vertex.
Here is the code of my program:
int n, a[10][10], i, j, k, c[10], max = 0, col, ct = 0, rt = 0, m, count = 2;
void main() {
printf("enter n\n");
scanf("%d", &n);
printf("enter the Adjacency Matrix for %d rows and %d columns\n", n, n);
for (i = 0; i < n; i++) {
c[i] = 0;
for (j = 0; j < n; j++)
scanf("%d", &a[i][j]);
}
c[0] = 1;
c[1] = 2;
for (i = 1; i < n; i++) {
for (j = 0; j < n; j++)
if (a[i][j] > 0) {
m = 0;
for (col = 0; col < n; col++) {
if (a[i][col] > 0)
rt++;
if (a[col][i] > 0)
ct++;
}
m = rt;
if (ct > rt)
m = ct;
if (m < 2) {
if (a[0][i] > 0)
c[i] = 2;
else
c[i] = 1;
} else {
c[i] = count;
if (m > max) {
max = m;
count++;
}
}
rt = 0;
ct = 0;
}
if (c[i] < 1)
if (c[i - 1] > 1)
c[i] = 1;
else
c[i] = 2;
}
printf("The proper coloring is\n");
for (i = 0; i < n; i++)
printf("c%d=%d ", i + 1, c[i]);
printf("\n");
}
Example Input:
Consider a complete graph:
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
Expected output:
c1=1 c2=2 c3=3 c4=4
Observed output:
c1=1 c2=2 c3=3 c4=3
The error seems to be in logic, as you may have inferred by the looks of the question title. The conditional statement where you are checking if m is greater than max and then updating max and count accordingly seem to be incorrect.
I could not exactly figure out what the intended logic was, but I can tell why it is incorrect.
In your usage, you keep the maximum number of neighbors you encountered in max, and update it when you find a vertex which has more neighbors. With it, you also update count, which I think holds the color of currently highest value. Now, unless you encounter a vertex with more neighbors at each step(while traversing each row), you don't update max, and therefore you don't update count. Consequently, unless you encounter such a vertex, you keep assigning the same currently highest count to all vertices you encountered.
You should explain some more about the algorithm you implemented. However, just by looking at your code I think you should at least increment count somewhere different.
A good idea might by just keeping an array equal to the number of vertices. Then for each vertex (inside outermost loop) you can reset the array and by traversing all of the neighbors of ith vertex you can set the colors used in them, and pick the smallest unused color.
It is probably not the most efficient way to do it, but you already have an O(n3) algorithm, so I think it wouldn't hurt going this way.
Below is your code, updated to reflect the changes I mentioned.
int n,a[10][10],i,j,k,c[10],max=0,col,ct=0,rt=0,m,count=2;
int used[11]; /* indices used are from 1 to n, inclusive */
void main()
{
printf("enter n\n");
scanf("%d",&n);
printf("enter the Adjacency Matrix for %d rows and %d columns\n",n,n);
for(i=0; i < n ; i++)
{
c[i]=0;
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
}
c[0]=1;
c[1]=2;
for(i = 1 ;i < n;i++)
{
for(j = 1 ;j <= n ;j++)
used[j] = 0;
for(j = 0 ;j < i ;j++)
{
if(a[i][j] > 0)
used[c[j]] = 1;
}
for(j = 1 ;j <= n ;j++)
if(!used[j])
{
c[i] = j;
break;
}
}
printf("The proper coloring is\n");
for(i = 0;i < n ;i++)
printf("c%d=%d ",i+1,c[i]);
printf("\n");
}
What does a straightforward algorithm to colour the verices look like?
Consider all vertices in a loop and assign a colour. Vertices that have been visited already have a colour; vertices that will still be visited are still uncoloured.
Determine which colours are used by adjacent vertices that have already been coloured.
With this information, pick the lowest possible colour.
What does your algorithm look like:
Assign colour 1 to vertex 1 and colour 2 to vertex 2. (Note that vertex 2 can use the same colour as vertex 1 if the two aren't connected.)
Loop over all remaining vertices; then loop over all vertices cnnected to that.
Count the number of incoming and outgoing links to the second vertex in yet another loop. (Note that merely counting the links doesn't give you information on which colours are still available. You could have many vertices coloured with colours 3 and 4, for example, but you base your new colour on the number of links. In this example, colour 1 would be a good choice.)
Your criterion for chosing a new colour is whether the number of links is greater or equal to 2. You then assign the count, but before incrementing it. That gives you the second 3 in your example, where there should be a 4.
So you loop once too many and have a poor criterion for choosing a colour. Instead of counting the lonks, you should keep a list of used colours in adjacent nodes and base your new colour on that list.
Other stylistic issues with your code:
All your variables should be local to main; there's no reason to make them global, especially since you don't use functions.
Please be more systematic with your variable declarations. To have them all slapped together in one large definition, which even claoesces arrays and scalars, make them hard to understand.
Please use braces around all code blocks, even if they are not strictly necessary. It makes reading the code easier. Small if s without an else in the inner block such as if (ct > rt) m = ct; don't need braces, but consider using them everywhere else.
UPDATE: Thanks a lot M Oehm for your awesome answer, really helped me a lot. That struct pos moves is really helpful, haven't studied it yet on class. Im working on a fully solution of my code adding yours as a bone on the programs skeleton. Already fixed the problem of updating fila and columna, the random choice and the switch from 0 to 7 without the ' ' because they're not characters as you and davidc pointed. My program still have some problems which im working on before posting the fully operational program here. I'll update the code tomorrow if not today. Thank you all for your comments and solutions, and M oehm for the time you spent making that wonderful answer.
------------------------------------------------------------------------------------------------------------------------------------
UPDATE 2: Finnished it, made some little changes on M Oehm code and instead of putting manually the first location of the horse i used my previous PosicionCaballo(). Had to delete the code of the MoverCaballo() which had a Switch with 8 possible moves which was set by a random number because i couldn't make it work (i guess the main problem was that part because already was a mess). Now the program with the code below should ask the user for the initial position of the horse, after that the screen will print a 10x10 table filled with 0's (free spaces), fill it with 1's (taken spaces which did the horse moving randomly) and when it finnishes display a message on how many positions did it take.
COORD cxy;
#define posicion(x,y) {(cxy.X)= (x);(cxy.Y)= (y); SetConsoleCursorPosition((GetStdHandle(STD_OUTPUT_HANDLE)), (cxy) );}
int ajedrez[10][10];
int fila, columna;
void GenerarTablero(int m[10][10]){
int i, j;
for (i = 0; i < 10; i++){
for (j = 0; j < 10; j++){
m[i][j] = 0;
}
}
}
GenerarTablero makes the chess board and fills it with 0's.
Global are fila (row) and columna (column) the parts of the ajedrez[10][10]
ajedrez[10][10] is the chess table in a 10x10 size.
void PosicionCaballo(int m[10][10]){
printf("Fila: ");
scanf_s("%d", &fila);
printf("Columna: ");
scanf_s("%d", &columna);
printf("\n");
m[fila][columna] = 2;
system("cls");
}
PosicionCaballo does ask the user for the initial position of the horse and puts the horse on the table.
Example: Row: 5 Column: 5
int horse(int y, int x)
{
int visited[SIZE][SIZE] = { { 0 } };
int count = 0;
if (on_board(y, x) == 0) return -1;
/* Set starting position */
visited[y][x] = 1;
while (1) { /* Infinite loop - must use break */
int poss[8]; /* Possible moves */
int nposs = 0; /* Actual length of poss */
int i, k = 1;
for (i = 0; i < 8; i++) {
int xx = x + moves[i].x;
int yy = y + moves[i].y;
if (on_board(yy, xx) && visited[yy][xx] == 0) {
poss[nposs++] = i;
}
}
/* No more valid moves: return */
if (nposs == 0){
posicion(0, 11);
printf("El tablero se ha bloqueado con ");
return count;
}
/* pick one of the valid moves */
i = poss[rand() % nposs];
x = x + moves[i].x;
y = y + moves[i].y;
/* update horse's position */
visited[y][x] = 1;
count++;
/* print position */
posicion(y, x);
printf("1");
}
return -1; /* Should never be reached */
}
void MostrarMapa(int m[10][10]){
int i, j;
for (i = 0; i < 10; i++){
for (j = 0; j < 10; j++){
printf("%d", ajedrez[i][j]);
}
printf("\n");
}
}
MostrarMapa only prints the chess table on the screen.
int main(void){
int n;
srand(time(NULL));
GenerarTablero(ajedrez);
PosicionCaballo(ajedrez);
MostrarMapa(ajedrez);
n = horse(fila, columna);
posicion(31, 11);
printf("%d movimientos\n", n);
getch();
return 0;
}
and then my main which im using all the functions stated upside.
Thank you very much in advance for your help guys :).
I guess that your assignment is about finding a valid path that visits all squares. Your code tries to find one random path.
Your code has several errors:
When you test ajedrez[fila - 2][columna - 1], you don't check whether fila - 2 or columna - 1 are really valid indices of your chess board. If you access invalid indices, way -1 or 11, you invoke undefined behaviour.
You don't update fila and columna, that is: You don't move your horse.
You overwrite the board twice. That's not an error, but your code shouldn't do double duty.
Your random choice is broken. You have eight possible moves, so you want rand() % 8, which yields numbers from 0 to 7. (David has already pointed this out in a comment.)
Your case labels are charater constants, not numbers. Use case 0:, not case '0':.
You just skip invalid moves. When there are no more valid moves, this will result in an infinite loop. You should check this condition and terminate the loop if it occurs.
As I understand it, the ´posicion` macro is just to show ehere the horse is. Maybe you should skip that at the moment and just print the new coordinates, which isn't as pretty, but straightforward.
Your eight switch cases manifest another flaw: You have the same repeated code eight times over. The only difference is the jump pattern. Such a set-up lends itself to either writing a function where you pass the row and columns distance to jump or to using an array of possible jump patterns.
Your code should instead do something like this for each move:
Loop over all eight jump patterns. If the horse would jump off the board or if the horse would visit a tile that has already been visited, skip that possibility. Otherwise, add the move to an auxiliary array.
If the number of possibilities is zero, terminate the loop - the horse has nowhere to go.
Pick one of the valid moves.
Move the horse, mark the current tile visited.
Report the jump, if desired: Print the new position or place the cursor, whatever.
Below is an example implementation that uses an array of jump patterns. It will give one random path. You can adapt this code to your problem.
#include <stdlib.h>
#include <stdio.h>
#include <time.h> /* for time() */
#define SIZE 10 /* Fixed board size */
struct pos {
int x, y;
};
struct pos moves[8] = { /* Jump patterns */
{1, 2},
{2, 1},
{2, -1},
{1, -2},
{-1, -2},
{-2, -1},
{-2, 1},
{-1, 2}
};
/*
* Is position (y, x) a valid board coordinate?
*/
int on_board(int y, int x)
{
if (x < 0 || x >= SIZE) return 0;
if (y < 0 || y >= SIZE) return 0;
return 1;
}
/*
* Move the horse randomly, starting from (y, x). Print the
* visited fields and return the number of moves made or
* -1 if an error occurs.
*/
int horse(int y, int x)
{
int visited[SIZE][SIZE] = {{0}};
int count = 0;
if (on_board(y, x) == 0) return -1;
/* Set starting position */
visited[y][x] = 1;
printf("%c%d, ", 'A' + y, x + 1);
while (1) { /* Infinite loop - must use break */
int poss[8]; /* Possible moves */
int nposs = 0; /* Actual length of poss */
int i;
for (i = 0; i < 8; i++) {
int xx = x + moves[i].x;
int yy = y + moves[i].y;
if (on_board(yy, xx) && visited[yy][xx] == 0) {
poss[nposs++] = i;
}
}
/* No more valid moves: return */
if (nposs == 0){
printf("whoa!\n");
return count;
}
/* pick one of the valid moves */
i = poss[rand() % nposs];
x = x + moves[i].x;
y = y + moves[i].y;
/* update horse's position */
visited[y][x] = 1;
count++;
/* print position */
printf("%c%d, ", 'A' + y, x + 1);
}
return -1; /* Should never be reached */
}
int main()
{
int n;
srand(time(NULL));
n = horse(3, 6);
printf("%d moves\n", n);
return 0;
}
You seem to update the position using posicion(), but not update fila and columna
Thanks for helping. I really appreciate it. I Have been searching for solution on SO, but nothing is exactly what I need. I need it in C.
My task is to find "largest square" of 1's in an array. The array consists of only 0's and 1's and looks, for example, like this:
4 4
0 1 1 1
0 1 0 1
0 1 1 1
1 0 1 0
Output should print [row][col] of "upper left corner" 1, and [row][col] of "lower right corner", So it should be, for my example, [0][1] and [2][3].
I am using my getcolor() function to get value on [row][col] spot.
Also, I have these functions to get longest horizontal and vertical lines. For some reason they only work with arrays with the same number of columns and rows. When I use, for example, an array with 4 cols and 5 rows, it does not work right. Aan you help me please?
void getHline(Bitmap *arr)
{
int i, j, k;
int line, line_start, line_end, line_max = 0;
// Horizontally
for (k = 0; k < arr->rows; k++)
{
for (i = 0; i < arr->rows; i++)
{
if(!getcolor(arr, k, i))
{
continue;
}
for(j = i; j < arr->cols; j++)
{
if(!getcolor(arr, k, j))
{
break;
}
}
j--;
if(j - i + 1 > line_max)
{
line = k;
line_start = i;
line_end = j;
line_max = line_end-line_start+1;
}
}
}
printf("horizontally\n");
printf("start: [%d][%d]\n", line_start, line);
printf("end: [%d][%d]\n", line_end, line);
}
void getVline(Bitmap *arr)
{
int i, j, k;
int col, col_start, col_end, col_max = 0;
for(k = 0; k < arr->cols; k++)
{
for (i = 0; i < arr->rows; i++)
{
if (!getcolor(arr,i,k)) continue;
for (j = i; j <arr->cols; j++)
{
if (!getcolor(arr,j,k)) break;
}
j--;
if (j - i + 1 >col_max)
{
col = k;
col_start = i;
col_end = j;
col_max = col_end-col_start+1;
}
}
}
printf("\nverticaly\n");
printf("start: [%d][%d]\n", col, col_start);
printf("end: [%d][%d]\n", col, col_end);
}
If you're trying to get the largest square this has noting to do with the longest horizontal and vertical lines, because they could be separated and no square associated with them.
When trying to solve a complex problem, don't try to solve it all at once.
The first thing we have, is that each point of the array is associated with a square (the largest one for each point). So we have to find that square: We take a point of the array, then we move by steps through a continuous horizontal and vertical lines. For each step we check if we get a square and repeat the process until we get the largest square associated with that single point.
Each time we get the largest square associated with a point we check if it's largest than the last largest square associated with some previous point.
After connecting these parts we get our final program.
Explanation of the variables used in the program:
Link to the program http://pastebin.com/Yw05Gbtg or view it here:
EDIT:
#include <stdio.h>
main()
{
int lines=4, cols=4;
int arr[4][4] = {
{0,1,1,1,},
{0,1,0,1,},
{0,1,1,1,},
{1,0,1,0,}
};
int x_start, y_start, x_end, y_end, d_max=0;
int i, j, k, l;
int col_start, line_start, col_end, line_end, checker;
for (y_start=0; y_start<lines; y_start++){
for (x_start=0; x_start<cols; x_start++){
x_end = x_start;
y_end = y_start;
for (i=x_start, j=y_start; i<cols && j<lines; i++, j++){ // moving horizontally and vertically
if (!arr[y_start][i] || !arr[j][x_start]){ // checking if the horizontal or vertical lines are not continuous
break;
}
else {
checker = 1;
for (k=x_start, l=y_start; k<i+1 && l<j+1; k++, l++){ // check if square
if (!arr[j][k] || !arr[l][i]){
checker = 0;
break;
}
}
if (checker){ // if square then
x_end = i;
y_end = j;
}
}
}
if ((x_end-x_start)>d_max){
col_start = x_start;
line_start = y_start;
col_end = x_end;
line_end = y_end;
d_max = col_end-col_start;
}
}
}
printf("The largest square is:\n[%d][%d] x [%d][%d]\n", line_start, col_start, line_end, col_end);
// this is only to check if the program is working properly
for (y_start=line_start; y_start<line_end+1; y_start++){
printf("\n ");
for (x_start=col_start; x_start<col_end+1; x_start++){
printf("%d ", arr[y_start][x_start]);
}
}
printf("\n");
}
There is confusion between rows and cols somewhere in your code. To find it, rename your variables i, j and k to something more meaningful, like row, col_start and col_end.
As for finding maximal square, you might want to use prefix sums.