Tuesday, December 23, 2014

Star

This one is from hacker rank.

https://www.hackerrank.com/challenges/stars


Problem Statement from the hacker rank
Little John has drawn N stars on his paper where each star has a weight vi. He draws a straight line that divides the paper into two parts such that each part has a subset of stars in them. Let the weight of each part be the summation of weights of the stars in the part. He wants to draw the line such that the difference in the sum of weights between the two parts is as small as possible while maximizing the smaller part's weight.
Your task is to compute the weight of smaller part corresponding to this line where no stars are allowed to be on the line and line can be of any slope.
Input Format
The first line of the input contains an integer N.
Each of next N lines contains three integers xi and yi specifying the positions of ith star and vi.
No three points lie on a line.
The key here is the formular to find if point is on left or right side of a line:
position = sign( (Bx-Ax)*(Y-Ay) - (By-Ay)*(X-Ax) )
0 on the line, and positive on one side, negative on the other side.

this is O(n^3) solution
public class Solution {
    public static class Point{
        long x; long y; long w;
        Point(long x, long y, long w){this.x = x; this.y = y; this.w = w;}
        long onLine(Point p1, Point p2){
            return (p1.x - p2.x)*(this.y-p1.y)-(p1.y-p2.y)*(this.x-p1.x);
        }
    }

    public static void main(String[] args) {
        /* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */
        try(Scanner conin = new Scanner(System.in)){
            int num = conin.nextInt();
            Point[] points = new Point[num];
            for(int i=0; i<num; i++){
                points[i] = new Point(conin.nextLong(), conin.nextLong(), conin.nextLong());
            }
            long maxSum = 0;
            for(int i=0; i<num; i++){
                for(int j=i+1; j<num; j++){
                    long leftSum = 0;
                    long rightSum = 0;
                    for(int k=0; k<num; k++){
                        if(!(k==i || k==j)){
                            long left = points[k].onLine(points[i], points[j]);
                            if(left>0)
                                leftSum += points[k].w;
                            else
                                rightSum += points[k].w;
                        }                        
                    }
                    
                    long[] sums = new long[]{leftSum, rightSum, points[i].w, points[j].w};
                    Arrays.sort(sums);
                    long sum = Math.min(sums[0]+sums[3], sums[1]+sums[2]);
                    maxSum = Math.max(maxSum, sum);
                    
                    //sum = Math.min(sums[0], sums[1]+sums[2]+sums[3]);
                    //maxSum = Math.max(maxSum, sum);
                    
                    sum = Math.min(sums[0]+sums[1], sums[2]+sums[3]);
                    maxSum = Math.max(maxSum, sum);
                    
                    sum = Math.min(sums[0]+sums[1]+sums[2], sums[3]);
                    maxSum = Math.max(maxSum, sum);
                    
                }
            }
            System.out.println(maxSum);
        }
    }
}

1 comment:

  1. Can you please elaborate the logic. Here, position = sign( (Bx-Ax)*(Y-Ay) - (By-Ay)*(X-Ax) ), Why X and Y are taken from existing points when there is a restriction of point not lying on the separating line.

    ReplyDelete