Find the shortest path with maximum gain - java

Problem link How can i modify my code so it give me shortest path with maximum weight.
Problem overview: I am giving a matrix and i have to go from one index to other with minimum index each index is having some gain , so i have to find the shortest path(if more than one shortest path are possible so path with maximum gain)
My code:
public static int min(int x , int y ,int endx,int endy,int n ,int m,int[][] p){
int[] dirx ={1,-1,0,0 };
int[] diry={0,0,1,-1};
LinkedList<Point> som = new LinkedList<Point>();
som.add(new Point(x,y));
//dp[x][y]=p[x][y];
while(!som.isEmpty()){
Point xx = som.pop();
for(int i=0;i<4;i++){
int x1 = xx.x + dirx[i];
int y1 = xx.y + diry[i];
if(x1>=0 && x1<n && y1>=0 && y1<m && p[x1][y1]!=-1 && dp[x1][y1]==-1){
dp[x1][y1] = dp[xx.x][xx.y]+ 1;
som.add(new Point(x1,y1));
}
}
}
return dp[endx][endy];
}

from your code add
((dp[x1][y1]==-1) || ((dp[x1][y1] == dp[xx.x][xx.y] + 1) && (w[xx.x][xx.y]+p[x1][y1] > w[x1][y1])))
instead of
(dp[x1][y1]==-1)
and inside the condition
w[x1][y1] = w[xx.x][xx.y] + p[x1][y1];
which means you will update the path result if you found better way of the same length
also you may optimize not to add same point several times, but i think this is not necessary in this particular problem

This problem can be solved using Dijkstra's algorithm. But we need to compare both distance and gain amount instead of just distance in the original algorithm.
These are some code hints from me, so you only need to change some part of your code.
class Entry implements Comparable<Entry>{
int x,y, dist, gain;
//Constructor is omitted.
public int compareTo(Entry o){
if(dist != o.dist)//Compare distance first
return dist - o.dist;
return o.gain - gain;//Compare gain value
}
}
//Method signature is omitted
PriorityQueue<Entry> q = new PriorityQueue();
q.add(new Entry(0,0,0,gain[0][0]);
int[][][]dist = new int[n][m][2];//Assume size of matrix is n x m
//Init dist array omitted
dist[0][0][0] = 0;//Init distance
dist[0][0][1] = gain[0][0];//Init gain amount, assume we have a gain matrix
while(!q.isEmpty()){
Entry e = q.poll();
if(dist[e.x][e.y][0] == e.dist && dist[e.x][e.y][1] == e.gain){
for(all valid next positions (a,b))
if(dist[a][b][0] > e.dist + 1 || (dist[a][b][0] == e.dist + 1 && dist[a][b][1] < e.gain + gain[a][b]){
//Notice the condition to update the dist array
dist[a][b][0] = e.dist + 1;
dist[a][b][1] = e.gain + gain[a][b];
q.add(new Entry(a,b,e.dist + 1, e.gain + gain[a][b]);
}
}
}
return dist[n-1][m-1][1];

Related

Maximum height of the staircase

Given an integer A representing the square blocks. The height of each square block is 1. The task is to create a staircase of max height using these blocks. The first stair would require only one block, the second stair would require two blocks and so on. Find and return the maximum height of the staircase.
Your submission failed for the following input: A : 92761
Your function returned the following : 65536
The expected returned value : 430
Approach:
We are interested in the number of steps and we know that each step Si uses exactly Bi number of bricks. We can represent this problem as an equation:
n * (n + 1) / 2 = T (For Natural number series starting from 1, 2, 3, 4, 5 …)
n * (n + 1) = 2 * T
n-1 will represent our final solution because our series in problem starts from 2, 3, 4, 5…
Now, we just have to solve this equation and for that we can exploit binary search to find the solution to this equation. Lower and Higher bounds of binary search are 1 and T.
CODE
public int solve(int A) {
int l=1,h=A,T=2*A;
while(l<=h)
{
int mid=l+(h-l)/2;
if((mid*(mid+1))==T)
return mid;
if((mid*(mid+1))>T && (mid!=0 && (mid*(mid-1))<=T) )
return mid-1;
if((mid*(mid+1))>T)
h=mid-1;
else
l=mid+1;
}
return 0;
}
To expand on the comment by Matt Timmermans:
You know that for n steps, you need (n * (n + 1))/2 blocks. You want know, if given B blocks, how many steps you can create.
So you have:
(n * (n + 1))/2 = B
(n^2 + n)/2 = B
n^2 + n = 2B
n^2 + n - 2B = 0
That looks suspiciously like something for which you'd use the quadratic formula.
In this case, a=1, b=1, and c=(-2B). Plugging the numbers into the formula:
n = ((-b) + sqrt(b^2 - 4*a*c))/(2*a)
= (-1 + sqrt(1 - 4*1*(-2B)))/(2*a)
= (-1 + sqrt(1 + 8B))/2
= (sqrt(1 + 8B) - 1)/2
So if you have 5050 blocks, you get:
n = (sqrt(1 + 40400) - 1)/2
= (sqrt(40401) - 1)/2
= (201 - 1)/2
= 100
Try it with the quadratic formula calculator. Use 1 for the value of a and b, and replace c with negative two times the number of blocks you're given. So in the example above, c would be -10100.
In your program, since you can't have a partial step, you'd want to truncate the result.
Why are you using all these formulas? A simple while() loop should do the trick, eventually, it's just a simple Gaussian Sum ..
public static int calculateStairs(int blocks) {
int lastHeight = 0;
int sum = 0;
int currentHeight = 0; //number of bricks / level
while (sum <= blocks) {
lastHeight = currentHeight;
currentHeight++;
sum += currentHeight;
}
return lastHeight;
}
So this should do the job as it also returns the expected value. Correct me if im wrong.
public int solve(int blocks) {
int current; //Create Variables
for (int x = 0; x < Integer.MAX_VALUE; x++) { //Increment until return
current = 0; //Set current to 0
//Implementation of the Gauss sum
for (int i = 1; i <= x; i++) { //Sum up [1,*current height*]
current += i;
} //Now we have the amount of blocks required for the current height
//Now we check if the amount of blocks is bigger than
// the wanted amount, and if so we return the last one
if (current > blocks) {
return x - 1;
}
}
return current;
}

RandomWalk solution issue

PROBLEM
I am working on a code where I am simulating a dog walking in a city - trying to escape the city. The dog makes random choices of which way to go to at each intersection with equal probability.If stuck at a dead end the dog will come directly back to the middle of a big city and start all over again. The dog will do this again and again until it gets out of the city or until it gets tired after T number of trials. But by the time the the dog starts again from the middle(N/2,N/2) on each try, it will have forgotten all the intersections it had visited in the previous attempt.
IDEA
The idea is to mimic a code given in our textbook and come up with the solution. We were given input N, T - where N is the number of north-south and east-west streets in the city and T is the number of times the dog will try to get out of the city before it gives up. We have to draw it out, using StdDraw. We have been given how to make random movements - generate a number between 0 and 4 - up: 0 right: 1 down: 2 left: 3
My Approach
import java.util.Random;
public class RandomWalk {
private static final Random RNG = new Random (Long.getLong ("seed",
System.nanoTime()));
public static void main(String[] args) {
int N = Integer.parseInt(args[0]); // lattice size
int T = Integer.parseInt(args[1]); // number of trials
int deadEnds = 0; // trials resulting in a dead end
StdDraw.setCanvasSize();
StdDraw.setXscale(0,N);
StdDraw.setYscale(0,N);
// simulate T self-avoiding walks
for (int t = 0; t < T; t++) {
StdDraw.clear();
StdDraw.setPenRadius(0.002);
StdDraw.setPenColor(StdDraw.LIGHT_GRAY);
for(int i=0;i<N;i++){
StdDraw.line(i, 0, i, N);
StdDraw.line(0, i, N, i);
}
StdDraw.setPenColor(StdDraw.RED);
StdDraw.setPenRadius(0.01);
boolean[][] a = new boolean[N][N]; // intersections visited
int x = N/2, y = N/2; // current position
// repeatedly take a random step, unless you've already escaped
while (x > 0 && x < N-1 && y > 0 && y < N-1) {
int t_x = x;
int t_y=y;
// dead-end, so break out of loop
if (a[x-1][y] && a[x+1][y] && a[x][y-1] && a[x][y+1]) {
deadEnds++;
break;
}
// mark (x, y) as visited
a[x][y] = true;
// take a random step to unvisited neighbor
int r = RNG.nextInt(4);
if (r ==3) {
//move left
if (!a[x-1][y])
t_x--;
}
else if (r == 1 ) {
//move right
if (!a[x+1][y])
t_x++;
}
else if (r == 2) {
//move down
if (!a[x][y-1])
t_y--;
}
else if (r == 0) {
//move up
if (!a[x][y+1])
t_y++;
}
StdDraw.line(t_x, t_y, x, y);
x = t_x;
y = t_y;
}
System.out.println("T: "+t);
}
System.out.println(100*deadEnds/T + "% dead ends");
}
}
ISSUE
Given N - 15, T - 10, -Dseed=5463786 we should get an output like - http://postimg.org/image/s5iekbkpf/
I am getting - see http://postimg.org/image/nxipit0pp/
I don't know where I am going wrong. I know this is very specific in nature, but I am really confused so as to what I am doing wrong. I tried all 24 permutations of 0,1,2,3 but none of them gave the output desired. So, I conclude that the issue in in my code.
check your StdDraw.java with:
http://introcs.cs.princeton.edu/java/stdlib/StdDraw.java.html
your code should be fine, I got the expected result

Binary search for square root [homework]

For an assignment I must create a method using a binary search to find the square root of an integer, and if it is not a square number, it should return an integer s such that s*s <= the number (so for 15 it would return 3). The code I have for it so far is
public class BinarySearch {
/**
* Integer square root Calculates the integer part of the square root of n,
* i.e. integer s such that s*s <= n and (s+1)*(s+1) > n
* requires n >= 0
*
* #param n number to find the square root of
* #return integer part of its square root
*/
private static int iSqrt(int n) {
int l = 0;
int r = n;
int m = ((l + r + 1) / 2);
// loop invariant
while (Math.abs(m * m - n) > 0) {
if ((m) * (m) > n) {
r = m;
m = ((l + r + 1) / 2);
} else {
l = m;
m = ((l + r + 1) / 2);
}
}
return m;
}
public static void main(String[] args) {
//gets stuck
System.out.println(iSqrt(15));
//calculates correctly
System.out.println(iSqrt(16));
}
}
And this returns the right number for square numbers, but gets stick in an endless loop for other integers. I know that the problem lies in the while condition, but I can't work out what to put due to the gap between square numbers getting much bigger as the numbers get bigger (so i can't just put that the gap must be below a threshold). The exercise is about invariants if that helps at all (hence why it is set up in this way). Thank you.
Think about it: Math.abs(m*m-n) > 0 is always true non-square numbers, because it is never zero, and .abs cannot be negative. It is your loop condition, that's why the loop never ends.
Does this give you enough info to get you going?
You need to change the while (Math.abs(m * m - n) > 0) to allow for a margin of error, instead of requiring it be exactly equal to zero as you do right now.
Try while((m+1)*(m+1) <= n || n < m * m)
#define EPSILON 0.0000001
double msqrt(double n){
assert(n >= 0);
if(n == 0 || n == 1){
return n;
}
double low = 1, high = n;
double mid = (low+high)/2.0;
while(abs(mid*mid - n) > EPSILON){
mid = (low+high)/2.0;
if(mid*mid < n){
low = mid+1;
}else{
high = mid-1;
}
}
return mid;}
As you can see above , you should simply apply binary search (bisection method)
and you can minimize Epsilon to get more accurate results but it will take more time to run.
Edit: I have written code in c++ (sorry)
As Ken Bloom said you have to have an error marge, 1. I've tested this code and it runs as expected for 15. Also you'll need to use float's, I think this algorithm is not possible for int's (although I have no mathematical proof)
private static int iSqrt(int n){
float l = 0;
float r = n;
float m = ((l + r)/2);
while (Math.abs(m*m-n) > 0.1) {
if ((m)*(m) > n) {
r=m;
System.out.println("r becomes: "+r);
} else {
l = m;
System.out.println("l becomes: "+l);
}
m = ((l + r)/2);
System.out.println("m becomes: "+m);
}
return (int)m;
}

Cut a polygon into 4 parts with equals area. java

I need to cut a convex not simple polygon by two perpendicular lines to divide it into 4 equal(area) parts.
I wrote a program, but it does not pass tests.
I think the reason is rounding errors or my function of calculating area.
Please check it, is it correct?
I use shoelace algorithm and heron's formula
Here is the code:
double calcArea() {
double result = 0;
if (size() > 4) {
int j = size() - 1;
for (int i = 0; i < size() - 1; i++) {
result += (points.get(i).getX() + points.get(j).getX())
*
(points.get(j).getY() - points.get(i).getY());
j = i;
}
result = result / (result >= 0 ? 2. : -2.);
} else if(size() == 3) {
double c,a,b, p;
c = Math.sqrt(Math.pow(points.get(0).getY()-points.get(1).getY(),2)+Math.pow(points.get(0).getX()-points.get(1).getX(),2));
a = Math.sqrt(Math.pow(points.get(1).getY()-points.get(2).getY(),2)+Math.pow(points.get(1).getX()-points.get(2).getX(),2));
b = Math.sqrt(Math.pow(points.get(0).getY()-points.get(2).getY(),2)+Math.pow(points.get(0).getX()-points.get(2).getX(),2));
p = (a + b + c) / 2.;
return Math.sqrt(p*(p-a)*(p-b)*(p-c));
}
return result;
}
What I do in:
finding of point(x, y) of cutting polygon.
I cut it by x = a in [ min(x), max(x)]
and calculate S'(part of polygon from x=min(x) to x=a)
if S' = S/2 , i take a for calculating value(a, *)
then the same with y = b whereb in [min(y), max(y)]
Is there more fast method?

Program using loops and random generator (beginning java)

A drunkard in a grid of streets randomly picks one of four directions and stumbles to the next intersection, then again randomly picks one of four directions, and so on. You might think that on average the drunkard doesn't move very far because the choices cancel each other out, but that is not the case. Represent locations as integer pairs (x,y). Implement the drunkard's walk over 100 intersections, starting at (0,0) and print the ending location
Can anyone help? I'm completely lost with using random generators and loops in the same program
Below is what I have. It complies fine but doesn't print anything and I'm not sure if I got the random 100 intersection thing right
import java.util.*;
class Drunkard {
int x, y;
Drunkard(int x, int y) {
this.x = x;
this.y = y;
}
void moveNorth() {
this.y -= 1;
}
void moveEast() {
this.x += 1;
}
void report() {
System.out.println("Hiccup: " + x + ", " + y);
}
}
class Four {
public static void main(String[] args) {
Random generator = new Random();
Drunkard drunkard = new Drunkard(100, 100);
int direction;
for (int i = 0; i < 100; i++) {
direction = Math.abs(generator.nextInt()) % 4;
if (direction == 0) { // N
drunkard.moveNorth();
} else if (direction == 1) { // E
drunkard.moveEast();
} else if (direction == 2) { // S
System.out.println("Should move South.");
} else if (direction == 3) { // W
System.out.println("Should move West.");
} else {
System.out.println("Impossible!");
}
System.out.drunkard.report();
}
}
}
your program will be:
initialization
loop: for 1 to 100, do:
i = random()
if i<=0.25 : go north
if i>0.25 and i<=0.5 : go south
if i>0.5 and i<= 0.75 : go east
if i>0.75 and i<= 1 : go west
end loop
show final point.
I see a variety of problems:
You are initializing your Drunkard's position to 100,100. The assignment said to initialize to 0,0.
System.out.drunkard.report() absolutely does not compile. Just call drunkard.report().
The instructions say to print the final location, so you need to move the call to drunkard.report() down one line, so that it is outside of the for loop.
You haven't written methods for moveSouth or moveWest. Write them and add calls to them in the appropriate place.
The class Four needs to be public in order to run it directly.
Good Java programming practices say that every class should be in its own file, but this probably goes against what your instructor asked you to do.
But, I don't think that's your problem. I think there's a problem with how/where you're trying to run the program. You say it compiles fine but doesn't print any output. You know that after it compiles there is another step to run the program, right?
To be clear, here's what you should be doing. At a command line, make sure you are in the directory where your .java file lives. I'm going to assume it's called Four.java. Type the following, hitting enter after each line. (Don't type the $ prompt)
$ javac *.java
$ java Four
I copied the code you posted above, fixed the problems I highlighted, and followed my own instructions above; it works perfectly.
You can use
int direction = (new Random()).nextInt(4);
And use this direction variable to determine where he walks to. I would use recursion in this case instead of a loop.
This starts at 0,0. Generates a random number to determine location and updates the location.
Not sure about the way you are generating the random number, this seems to work well for me.
Point currentLocation = new Point();
currentLocation.setLocation(0, 0);
Point newLocation = new Point(0,0);
Random random = new Random();
//make 100 moves
for(int i=0; i<100; i++)
{
int k = random.nextInt(4);
if(k == 0)
{
//use your drunkard method here
newLocation.setLocation(currentLocation.getX(), currentLocation.getY() + 5);
}
else if (k == 1)
{
//go south
newLocation.setLocation(currentLocation.getX(), currentLocation.getY() - 5);
}
else if (k == 2)
{
//go east
newLocation.setLocation(currentLocation.getX() + 5, currentLocation.getY());
}
else if(k == 3)
{
//go west
newLocation.setLocation(currentLocation.getX() - 5, currentLocation.getY());
}
currentLocation.setLocation(newLocation);
}
System.out.println(currentLocation);
}
You're not implementing your random generator to its full extent.
Random generator = new Random();
int direction = generator.nextInt(4); // This will return a random int
// between 0 and 3
Some other useful tricks when using Random() are as follows:
int i = generator.nextInt(4)+2; // This will return a random int
// between 2 and 5
I highly recommend you check out this if you'd really like to learn all of the neat tricks that you can do using the Random Class.
All i did for this is create a loop that generated a random number between -1 and 1, and summed the values 100 times. Do that for x and for y.
int x = 0;
int y = 0;
//intial = (0,0)
//North = (0, 1)
//South = (0, -1)
//East = (1, 0)
//West = (-1, 0)
for(int i = 0; i < 100; i++)
{
x += (int) (Math.random() * 3) + (-1);
y += (int) (Math.random() * 3) + (-1);
}
System.out.printf("The Drunkard is now located at: (%d, %d)", x, y);

Categories