0

Here is an algo coding question:

There are stones in two dimension array, and given a known length rope, determine what's the maximum number of stones you can use the rope to surround? (the rope must be enclosed).

I think the question is to find the loop in undirected graph with maximal number of nodes and upper bound of length and BFS seems a good way, but seems still NP-hard.

EDIT:

Here is an example: 5 stones in a plane. I listed three surroundings: black, red and blue. The length of each surrounding is the sum of its strings.

The question is equivalent to select n of N points by order x1,...xn with its sum = d(x1,x2)+d(x2,x3)+...+d(xn-1,xn)+d(xn,x1) <= C. Here n>1. What's the maximal n? enter image description here

Solution:

After some hints, I think it is nothing about the undirected graph. It is similar to the problem that selecting some elements from a given array equal to a target sum. But the difference is that the result depends on the selecting order, therefore we cannot select by the order from the given array. Here is my solution. But there are still a lot of duplicate searches, for example, if black loop is eligible, we have to search 4 times from each of its nodes.

double d(const vector<double> a, const vector<double> b)
{
    return sqrt((a[0] - b[0])*(a[0] - b[0]) + (a[1] - b[1])*(a[1] - b[1]));
}

//recursive
//out: current legal elements; sum: the sum of out; ct: the maximal number up to now
//visited: record the elements in out has been visited to void duplicate visit
//res: help to check the result in debuge
void help(vector<vector<double>> array, double target, vector<vector<double>> &out, int &sum, int & ct, vector<vector<vector<double>>> &res, vector<bool> &visited)
{
    for (int i = 0; i < array.size(); i++) //since it depends on the order of selection, we have to search from begining. visited helps us to skip the element already been in out. 
    {
        if (visited[i]) continue;
        else if (out.empty()) {out.push_back(array[i]); visited[i] = true;}
        else
        {
            vector<double> last = out.back(), first = out.front();
            if (sum + d(array[i], last) + d(array[i], first) <= target)
            {
                out.push_back(array[i]);
                sum += d(array[i], last);
                ct = max(ct, (int)out.size());
                visited[i] = true;
                help(array, target - d(array[i], last), out, sum, ct, res, visited);
                out.pop_back();//when the loop is over at this level, we should return to the state of previous level
                sum -= d(array[i], last);
                visited[i] = false;
            }
            else
            {
                res.push_back(out);
                return;
            }
        }
    }
}
int Path(vector<vector<double>> array, double target) {
    int sum = 0, ct = 0; 
    vector<vector<double>> out;
    vector<vector<vector<double>>> res;
    vector<bool> visited(array.size(), false);
    help(array, target, out, sum, ct, res, visited);

    return ct;
}
user6703592
  • 1,004
  • 1
  • 12
  • 27
  • @kcsquared I don't understand `stone amounts are all nonnegative`. They are the points in the whole plane. And the question is selecting n points by order x1,...xn and calculate the sum d(x1,x2)+d(x2,x3)+...+d(xn-1,xn)+d(xn,x1). Here n>1. I also don't much understand your hint. Could you show more detail as a solution? – user6703592 Oct 31 '21 at 06:05
  • Can you give an example, or link to the source of the question? I'm having trouble following the description. – kcsquared Oct 31 '21 at 06:13
  • 1
    @kcsquared pls see my update – user6703592 Oct 31 '21 at 06:38
  • I see, I thought '2D array' was referring to a list of lists of integers, not points on the plane. As this is a geometry problem, my previous comments are irrelevant. Does the 'rope' have to pass *through* each stone it encloses? Can you just use the convex hull of the left 4 points (which is a triangle) in your example for a smaller perimeter? – kcsquared Oct 31 '21 at 06:49
  • If the rope needs to pass through each point it 'encloses', as the formula suggests, this is as hard as the [Euclidean travelling salesman problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem#Euclidean) which is NP-complete, but can be approximated well or solved in special cases. If the rope only needs to enclose the points, [see this thread](https://stackoverflow.com/questions/47006219/maximum-number-of-points-enclosed-in-given-perimeter), which asks that exact question (and has a polynomial time answer). – kcsquared Oct 31 '21 at 07:16
  • Given N points and a constant C, to solve: max n, s.t. d(x1,x2)+d(x2,x3)+...+d(xn-1,xn)+d(xn,x1) <= C, Where {x1,x2,...xn} are from N points. – user6703592 Oct 31 '21 at 07:41
  • Brute force: Find all cycles in the directed graph, select the cycle which satisfies the constraints and which has max number of nodes. – kiner_shah Oct 31 '21 at 11:55
  • @kiner_shah Yes, however it is NP hard. – user6703592 Oct 31 '21 at 11:58
  • You need not find all cycles, during processing you can prune off those cycles for which the rope length isn't sufficient. – kiner_shah Oct 31 '21 at 11:59
  • @kiner_shah you are right, actually it is nothing about the undirected graph. Pls see my solution. – user6703592 Oct 31 '21 at 13:15

0 Answers0