Dijkstra's Algorithm Assistance - java

Given an adjacency matrix, I need to compute the shortest path between the first vertex and the last vertex (generally, vertex i and j, but we can ignore that for the time being). I've written an algorithm that really only correctly computes the distance between the first and second node (a step in the right direction, I guess).
static int dijkstra(int[][] G, int i, int j) {
//Get the number of vertices in G
int n = G.length;
int[] bestpath = new int[n];
int max = Integer.MAX_VALUE;
boolean[] visited = new boolean[n];
for (int x = 0; x < n; x++) {
visited[x] = false;
bestpath[x] = max;
}
bestpath[i] = 0;
for (int x = 0; x < n; x++) {
int min = max;
int currentNode = i;
for (int y = 0; y < n; y++) {
if (!visited[y] && bestpath[y] < min) {
System.out.println(G[y][x]);
currentNode = y;
min = bestpath[y];
}
}
visited[currentNode] = true;
for (int y = 0; y < n; y++) {
if (G[currentNode][y] < max && bestpath[currentNode] + G[currentNode][y] < bestpath[y]) {
bestpath[y] = bestpath[currentNode] + G[currentNode][y];
}
}
}
return bestpath[j];
}
If I were to guess, I'd say my logic is flawed in this section:
for (int y = 0; y < n; y++) {
if (!visited[y] && bestpath[y] < min) {
System.out.println(G[y][x]);
currentNode = y;
min = bestpath[y];
}
}
An example would be the matrix
0 1 0
1 0 1
0 1 0
which would return 2 (one path between vertex one and two of weight 1 and another between 2 and 3 with weight 1).

If the matrix is not just storing 1s and 0s, but the distance from i to j, then you really need to keep track of the best distance from any node i to j. In other words, your working array should be a working matrix instead. Even if you are just doing a non - weighted graph, I think this approach is better.
There are different versions of the SPF algorithm. Post pseudocode for what you are trying to translate into java.

Related

What is the Best way to find AND-Product of all the possible pairs of large array?

The given array is too big contains 10^6 elements approx.
Already know traditional way of traversing each possible pair, but i want some more efficient way/trick.
int prod = 0, arr[]= {1,4};
for(int x = 0; x<arr.length;x++) {
for(int y = x;y<arr.length; y++) {
prod += arr[x] & arr[y];
}
}
System.out.println(prod);
// Count the occurrences of each bit
int[] bitcounts = new int[32];
for (int x=0; x<arr.length; ++x) {
int val = arr[x];
for (int bit=0; bit<32; ++bit) {
if ((val & (1<<bit)) != 0) {
bitcounts[bit]++;
}
}
}
// If a bit appears in n entries, then it appears in n(n+1)/2 pairs
// (counting the pair of each item with itself)
int result = 0;
for (int bit=0; bit<32; ++bit) {
long pairs = ((long)bitcounts[bit]) * (bitcounts[bit]+1) / 2;
result += ((int)pairs) * (1<<bit);
}
return result;
If arr[x]=0, you can skip the whole inner loop for that value of x (since 0&y=0 no matter what y is.
The diagonal is an identity.
prod = 0;
for(int x = 0; x < arr.length; x++) {
int ax = arr[x];
for(int y = x + 1; y <arr.length; y++) {
prod += ax & arr[y];
}
prod += arr[x];
}

How do i find the shortest distance of specified points between multiple points?

I've input the points and found distances between them. Now I want to find which distance of m points is shortest.
import java.awt.Point;
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
public class Solution
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
int k = in.nextInt();
Point[] coordinates=new Point[10];
double dist;
for(int i = 0; i < m; i++)
{
coordinates[i]=new Point(in.nextInt(),in.nextInt());
}
for(int i=0;i<m-1;i++)
{
dist=Math.sqrt(((coordinates[i+1].getX()-coordinates[i].getX())*(coordinates[i+1].getX()-coordinates[i].getX()))+((coordinates[i+1].getY()-coordinates[i].getY())*(coordinates[1].getY()-coordinates[0].getY())));
System.out.println("dist between "+coordinates[i+1].getX()+","+coordinates[i+1].getY()+"and "+coordinates[i].getX()+","+coordinates[i].getY() +" is "+dist);
}
in.close();
}
}
The way your for loop is designed, it is only checking one point with the point that was read just after it. You need 2 for loops to compare each of the points with all the others
for(int i = 0; i < m - 1; i++)
{
for (int j = 0; j < m; j++)
{
// compare point i with point j and store the smallest here
// you probably want to discard points where i == j
}
}
You have to make a for-loop inside another one to go through all points per point. The first for-loop will go through every point. The second loop will also go through all points, so inside the second loop, you will have any possible combination of two loops. Then you need to calculate the distance and check if the distance calculated is smaller than the smallest distance calculated before.
In the end you'll have the smallest distance:
0.0f for points[] being size 0 or 1
smallest distance for points[] being size 2 or greater
Here's some example code:
float smallesDistance = 0.0f;
Point[] points = ...;
for(int i = 0; i < points.length; i++) {
for (int j = 0; j < points.length; j++) {
if(i != j) { //cant compare on point with itself
Point a = points[i];
Point b = points[j];
float distance = ...; //calculate distance with pythagorean theorem
if(distance < smallesDistance)
smallesDistance = distance;
}
}
}
If you need the greatest distance, just replace if(distance < smallesDistance) by if(distance > smallesDistance).
Here are the helper functions:
distance: calculate the distance between two points
shortest_pair: return the pair with the shortest distance
Codes are as follows:
import java.awt.Point;
double distance(Point p1, Point p2)
{
return Math.sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}
int[] shortest_pair(Point[] coordinates)
{
int m = coordinates.length;
double shortest_distance = Double.MAX_VALUE;
int[] shortest_pair = new int[2];
for (int i = 0; i < m-1; i++)
{
for (int j = i+1; j < m; j++)
{
double d = distance(coordinates[i], coordinates[j]);
if (d < shortest_distance)
{
shortest_distance = d;
shortest_pair[0] = i;
shortest_pair[1] = j;
}
}
}
return shortest_pair;
}
Example is as follows:
Random rand = new Random();
rand.setSeed(0);
int m = coordinates.length;
assert m == 10;
for(int i = 0; i < m; i++)
coordinates[i] = new Point(rand.nextInt(10), rand.nextInt(10));
assert Arrays.equals(shortest_pair(coordinates), new int[] { 2, 7 });

Can't generate right graph for bellman-ford algorithm

I have an implementation of the algorithm of Bellman - Ford.
The input program supplied a list of edges.
Without optimization it looks like this:
int i, j;
for (i = 0; i < number_of_vertices; i++) {
distances[i] = MAX;
}
distances[source] = 0;
for (i = 1; i < number_of_vertices - 1; ++i) {
for (j = 0; j < e; ++j) { //here i am calculating the shortest path
if (distances[edges.get(j).source] + edges.get(j).weight < distances[edges.get(j).destination]) {
distances[edges.get(j).destination] = distances[edges.get(j).source] + edges.get(j).weight;
}
}
}
it has the complexity of O(V * E)
But with optimization his works very fast. it looks like
while (true) {
boolean any = false;
for (j = 0; j < e; ++j) { //here i am calculating the shortest path
if (distances[edges.get(j).source] + edges.get(j).weight < distances[edges.get(j).destination]) {
distances[edges.get(j).destination] = distances[edges.get(j).source] + edges.get(j).weight;
any = true;
}
}
if (!any) break;
}
In practice, if the number of vertices , for example ten thousand , in the outer loop had only 10-12 passes iterations instead of 10 thousand, and the algorithm completes its work .
This is my generate code:
//q - vertices
for (int q = 100; q <= 20000; q += 100) {
List<Edge> edges = new ArrayList();
for (int i = 0; i < q; i++) {
for (int j = 0; j < q; j++) {
if (i == j) {
continue;
}
double random = Math.random();
if (random < 0.005) {
int x = ThreadLocalRandom.current().nextInt(1, 100000);
edges.add(new Edge(i, j, x));
edges++;
}
}
}
//write edges to file edges
}
But I need to generate a graph on which it will not be so fast to finish his work. That can be changed in the generator?
The complexity of Bellman Ford algorithm like you said is O(|E|*|V|). In your generator, the probability of adding an edge is negligible (0.005) which is why according to me the code works fast.
Increase the probability, there shall be more edges and consequently the Bellman Ford shall then take longer time.

I'm building a MineSweeper Project and i need help counting adjacent mines

I'm trying to count the adjacent mines in my Array of tiles objects. The code works fine for any section of the grid within the boundary. let's assume it's a 10 by 10 array if I pick point 9,8 it will give me an array out of bounds exception. How can I make sure the Array will count the Adjacent mines on the edge of the array without giving me an ArrayOutOfBounds exception?
void countAdjacentMines(int x,int y) {
//Iterate through the array check if there is a mine
for (int i = 0; i < tiles.length; i++) {
for (int j = 0; j < tiles.length; j++) {
if ((tiles[i][j].getMine() == false)) {
int count = 0;
//Search adjacent tiles. at x,y
for (int p = x - 1; p <= x + 1; p++) {
for (int q = y - 1; q <= y + 1; q++) {
if (0 <= p && p < tiles.length && 0 <= q && q < tiles.length) {
if (tiles[p][q].getMine()==true)
count++;
}
tiles[p][q].setCount(count);
}
}
}
} // end for loop rows
} // end for loop columns
} // end countAdjacentMines
Create a function
int hasMine (int x, int x)
that returns 1 when (x,y) holds a mine,
or 0 if either it doesn't or (x,y) is not a valid cell (it is also useful
to have a boolean valid (int x, int y) function).
Then, just do:
totalMines = hasMine(x+1,y+1) + hasMine(x+1, y) + hasMine(x+1, y-1) + .... + hasMine (x-1,y-1) // 8 hasMine() calls.
The problem is due to
if (0 <= p && p < tiles.length && 0 <= q && q < tiles.length) {
if (tiles[p][q].getMine()==true)
count++;
}
tiles[p][q].setCount(count);
where the last statement isn't guarded by the test that p and q are within bounds.
But I think that the entire method isn't right: either you need to iterate the entire board and count, or you access a single place (x,y) and do the count for this one.

Shortest Path LinkedList

I want to find the shortest path on a list of linked list, which represents a directed graph with cost per edge/path.
The output would look something like this, It tells me the cost it would take me to get from vertex 0 to the other vertices:
d[0 to 0] = 0
d[0 to 1] = 20
d[0 to 2] = 10
This is how I populate my list for testing.
LinkedList<GraphData> g = new LinkedList[3];
for (int i = 0; i < 3; i++)
weight[i] = new LinkedList<GraphData>();
g[0].add(new GraphData(1, 20);
g[0].add(new GraphData(2, 10);
The GraphData class looks something like this:
int vertex, int edgeCost;
Now for my problem:
I want to find the shortest path from vertex v to all the others.
public static int[] shortestPaths(int v, LinkedList<GraphData>[] cost)
{
// get the set of vertices
int n = cost.length;
// dist[i] is the distance from v to i
int[] dist = new int[n];
// s[i] is true if there is a path from v to i
boolean[] s = new boolean[n];
// initialize dist
for(int i = 0; i < n; i++)
dist[i] = cost[v].get(i).getCost();
s[v] = true;
// determine n-1 paths from v
for ( int j = 2 ; j < n ; j++ )
{
// choose u such that dist[u] is minimal for all w with s[w] = false
// and dist[u] < INFINITY
int u = -1;
for (int k = 0; k < n; k++)
if ( !s[k] && dist[k] < INFINITY)
// check if u needs updating
if ( u < 0 || dist[k] < dist[u])
u = k;
if (u < 0)
break;
// set s[u] to true and update the distances
s[u]=true;
for (int k = 0; k < n; k++)
if ( !s[k] && cost[u].get(k).getCost() < INFINITY )
if( dist[k] > dist[u] + cost[u].get(k).getCost())
dist[k] = dist[u] + cost[u].get(k).getCost();
// at this point dist[k] is the smallest cost path from
// v to k of length j.
}
return dist;
}
This line dist[i] = cost[v].get(i).getCost(); throws "IndexOutOfBoundsException"
Any idea what I am doing wrong? Any help will be appreciated.
There are two common ways to represent graphs: adjacency lists and adjacency matrices.
Adjacency List: Array of lists. The element at index i is a small list containing the outgoing edges of vertex i. This is what you are creating when you populate the list.
Adjacency Matrix: Array of arrays, with cost[i][j] containing the cost of the edge from vertex i to vertex j. You are using the cost parameter as if it is an adjacency matrix.
You have two options:
Change the graph construction to create an adjacency matrix and use an array of arrays
Change the algorithm to treat cost as an adjacency list instead of an adjacency matrix
Here is the second option. I renamed a few things and simplified the initialization so that the first iteration calculates the distance to the immediate neighbours of v (as opposed to doing it as a special case at the start).
import java.util.*;
public class Main
{
public static int[] shortestPaths(int v, LinkedList<Edge>[] edges)
{
// get the set of vertices
int n = edges.length;
// dist[i] is the distance from v to i
int[] dist = new int[n];
for (int i = 0; i < n; i++) {
dist[i] = Integer.MAX_VALUE;
}
// seen[i] is true if there is a path from v to i
boolean[] seen = new boolean[n];
dist[v] = 0;
// determine n-1 paths from v
for (int j = 0; j < n; j++) {
// choose closest unseen vertex
int u = -1;
for (int k = 0; k < n; k++) {
if (!seen[k]) {
// check if u needs updating
if (u < 0 || dist[k] < dist[u]) {
u = k;
}
}
}
if (u < 0 || dist[u] == Integer.MAX_VALUE) {
break;
}
// at this point dist[u] is the cost of the
// shortest path from v to u
// set seen[u] to true and update the distances
seen[u] = true;
for (Edge e : edges[u]) {
int nbr = e.getTarget();
int altDist = dist[u] + e.getCost();
dist[nbr] = Math.min(dist[nbr], altDist);
}
}
return dist;
}
public static void main(String[] args)
{
int n = 5;
int start = 0;
LinkedList<Edge>[] cost = new LinkedList[n];
for (int i = 0; i < n; i++) {
cost[i] = new LinkedList<Edge>();
}
cost[0].add(new Edge(1, 20));
cost[0].add(new Edge(2, 10));
cost[1].add(new Edge(3, 5));
cost[2].add(new Edge(1, 6));
int[] d = shortestPaths(start, cost);
for (int i = 0; i < n; i++) {
System.out.print("d[" + start + " to " + i + "] = ");
System.out.println(d[i]);
}
}
}
class Edge
{
int target, cost;
public Edge(int target, int cost) {
this.target = target;
this.cost = cost;
}
public int getTarget() {
return target;
}
public int getCost() {
return cost;
}
}
Probably element cost[v].get(i) does not exist (no element with index i in this LinkedList which is cost[v]).
http://docs.oracle.com/javase/6/docs/api/java/util/LinkedList.html#get(int)
The problem is that your indices do not correspond. If you only put one distance, for instance
cost[0].add(new GraphData(5, 20));
then
cost[0].get(5).getCost();
will throw an IndexOutOfBoundsException, because you should do
cost[0].get(0).getCost();
in order to get 20 (which is very confusing).
I would advise using a Map, rather than a List to encode the edge costs.
You populate that Map like
List<Map<Integer, Integer>> g = new ArrayList<>();
for (int i = 0; i < 3; i++)
g.add(new HashMap<Integer, Integer>());
g.get(0).put(1, 20);
g.get(0).put(2, 10);
With this, you could initialize your dist array like
// initialize dist
for(int i = 0; i < n; i++)
dist[i] = cost.get(v).containsKey(i) ? cost.get(v).get(i) : INFINITY;

Categories

Resources