Accommodate maximum peoples in tour - algorithm

I have to arrange a tour. There are N peoples who want to attend the tour. But some of them are enemies with each other. (enemy of enemy may or may not be your enemy. If A is enemy of B, B is also enemy of A)
If I accommodate a person in my tour, I can not accommodate his enemy.
Now I want to accommodate maximum possible number of persons in the tour. How can I find this number?
ex: If there are 5 tourists, and let's call them A-E. A is enemy with B and D, B is enemy of E, and C is enemy of D.
A B C D E
+---+---+---+---+---+
A | - | X | | X | |
+---+---+---+---+---+
B | X | - | | | X |
+---+---+---+---+---+
C | | | - | X | |
+---+---+---+---+---+
D | X | | X | - | |
+---+---+---+---+---+
E | | X | | | - |
+---+---+---+---+---+
In this case following trips are possible: empty, A, B, C, D, E, AC, AE, BC, BD, ACE, CE, DE etc. Out of these, best tour is ACE as it accommodates 3 tourist and hence the answer 3.
My approach:
I tried looping and trying combinations with bitmaps, but they are
very slow.
I am currently using DFS but trying to find even a better
method.
I tried to work by creating friendship graph and prepare some
spanning tree. But it doesn't work as A can travel with B and B can
travel with C does not guarantee A and travel with C.
I tried by creating enemity graph and finding some weak links
but ended up clueless.
I would be thankful, if somebody can give me a hint or point to a good resource to solve this problem.

Create a graph from the tourists :
each node is a tourist
if two tourists are enemies draw an edge between them
find the maximum independent set
There are very well detailed algorithms for finding maximum independent set in this paper:
Algorithms for Maximum independent Sets
And a parallel approach has been provided in this one:Lecture Notes on a Parallel Algorithm for Generating a Maximal Independent Set
And this is a java implementation.

Firstly create an array of vectors-
vector<int> enemy[N];
and an array curr[N] telling if he is going or not.
If person x is going, curr[x]=1 else curr[x]=0
now call the given below function as f(0,0).
The answer will be in a global variable named "maxx", which is 0 initially.
void f(int i,int c)
{
// i is the index of current person we are seeing
// c is the total count of people going till now
if(i==N)
{
if(c>maxx)maxx=c;
}
else
{
int j,flag=1;
int sz;
sz=enemy[i].size();
if(sz==0)
{
//if he has no enemy, he can obviously go
curr[i]=1;
f(i+1,c+1);
}
else
{
for(j=0;j<sz;j++)
if(curr[enemy[i][j]]==1)
{
//if his enemy is already going, he cannot
flag=0;
break;
}
if(flag)
{
//if none of his enemies till now are going, he can
curr[i]=1;
f(i+1,c+1);
}
curr[i]=0;
f(i+1,c);//we will also see what if we dont take him
}
}

Try making an antagonism graph and then find a largest independent set. (Warning: this problem is NP)

Related

data structure for recombining tree: parents are permutations

I am trying to create a data structure which will describe a certain type of recombining "combinations" tree (similar to here).
First, consider a tree where each node has a particular ID which is described by the sequence needed to reach the node. As an example, take a fixed list Q = [1,2,3] and arrange the possible permutations of Q into a tree T based on the sequence diagram S:
S =
_0_
/ | \
1 2 3
/| / \ |\
2 3 1 3 1 2
| | | | | |
3 2 3 1 2 1
Then giving each node a letter, A, B, C,... the tree T can be represented by:
T =
_0_
/ | \
A B C
/| / \ |\
D E F G H I
| | | | | |
J K L M N O
where
A = {1}
B = {2}
C = {3}
D = {1,2}
E = {1,3}
F = {2,1}
G = {2,3}
H = {3,1}
I = {3,2}
J = {1,2,3}
K = {1,3,2}
L = {2,1,3}
M = {2,3,1}
N = {3,1,2}
O = {3,2,1}
Now, my goal is to come up with a data structure such that the tree that recombines in a way where nodes J and L are the same object (ie recombine), and similarly K and N recombine, and finally M and O recombine. The rule for recombining is that their parents D and F, E and H, and G and I contain the same elements, and the next element in the sequence is identical. In more detail, the rule resulting in equivalence between J and L is that their "parents" D and F are set equivalent (= {1,2}). I'm not sure how this would look for larger lists Q...
Do trees like this have a particular name? Are there any existing resources that I should look into, or any places I should start? Thanks!
It's not really useful to store this graph in any kind of data structure, since everything about it can be easily calculated without any kind of storage. You could store it in any kind of directed graph data structure if you really wanted to.
As a mathematical object, I would call it the "power set lattice" of Q, and anyone who knows the words would know what I mean, since it is the complete lattice over the power set.
A picture like the ones you are drawing is the "Hasse Diagram" of the power set: https://demonstrations.wolfram.com/HasseDiagramOfPowerSets/
You could also call it the "minimal deterministic finite automaton" for the set of permutations, but that leads to algorithms that are way more complicated than anything you will need.
Following up from the edit... I suppose it might be better to represent the various combinations at each level, that is, like:
level 0: |Q| choose 0 nodes
level 1: |Q| choose 1 nodes
level 2: |Q| choose 2 nodes
level 3: |Q| choose 3 nodes
and the various interconnections between them so that there 2^(N-1) * N such edges.

Finding the minimum number of calls on a tree

I was asked this question in an interview and struggled to answer it correctly in the time allotted. Nonetheless, I thought it was an interesting problem, and I hadn't seen it before.
Suppose you have a tree where the root can call (on the phone) each of it's children, when a child receives the call, he can call each of his children, etc. The problem is that each call must be done in a number of rounds, and we need to minimize the number of rounds it takes to make the calls. For example, suppose you have the following tree:
A
/ \
/ \
B D
|
|
C
One solution is for A to call D in round one, A to call B in round two, and B to call C in round three. The optimal solution is for A to call B in round one, and A to call D and B to call C in round two.
Note that A cannot call both B and D in the same round, nor can any node call more than one of its children in the same round. However, multiple nodes with a different parent can call simultaneously. For example, given the tree:
A
/ | \
/ | \
B C D
/\ |
/ \ |
E F G
We can have a sequence (where - separates rounds), such as:
A B - B E, A D - B F, A C, D G
(A calls B first round, B calls E and A calls D second, ...)
I'm assuming some type of dynamic programming can be used, but I'm not sure which direction to take this in. My initial inclination is to use DFS to order the longest path from the root to leaves in decreasing order, but when it comes to the nodes actually making calls, I'm not sure how we can achieve optimality given any tree, not how we can output the paths that the optimal calls would make (i.e. in the first example we could output
A B - B C, A D
I think something like this could get the optimal solution:
suppose the value of 'calls' for each of leaves is 1
for each node get the value of calls for all of his children and rank them according to their 'calls' value
consider rank of each child as 'ranks'
to compute the value of 'calls' for each node loop over his children (after computing their ranks) and find the maximum value of 'calls' + 'ranks'
'calls' value of the root node is the answer
It's sorta dynamic programming on trees and you can implement it recursively like this:
int f(node v)
{
int s = 0;
for each u in v.children
{
d[u] = f(u)
}
sort d and rank its values in r (r for the maximum u would be 1)
for each u in v.children
{
s = max(s, d[u] + r[u] + 1)
}
return s
}
Good Luck!

Similarity measurement of time-sequenced data with different length

Consider the following data.
Groundtruth | Dataset1 | Dataset2 | Dataset3
Datapoints|Time | Datapoints|Time | Datapoints|Time | Datapoints|Time
A |0 | a |0 | a |0 | a |0
B |10 | b |5 | b |5 | b |13
C |15 | c |12 | c |12 | c |21
D |25 | d |22 | d |14 | d |30
E |30 | e |30 | e |17 |
| | f |27 |
| | g |30 |
Visualized like this (as in number of - between each identifier):
Time ->
Groundtruth: A|----------|B|-----|C|----------|D|-----|E
Dataset1: a|-----|b|-------|c|----------|d|--------|e
Dataset2: a|-----|b|-------|c|--|d|---|e|----------|f|---|g
Dataset3: a|-------------|b|--------|c|---------|d
My goal is to compare the datasets with the groundtruth. I want to create a function that generates a similarity measurement between one of the datasets and the groundtruth in order to evaluate how good my segmentation algorithm is. Obviously I would like the segmentation algorithm to consist of equal number of datapoints(segments) as the groundtruth but as illustrated with the datasets this is not a guarantee, neither is the number of datapoints known ahead of time.
I've already created a Jacard Index to generate a basic evaluation score. But I am now looking into an evaluation method that punish the abundance/absence of datapoints as well as limit the distance to a correct datapoint. That is, b doesn't have to match B, it just has to be close to a correct datapoint.
I've tried to look into a dynamic programming method where I introduced a penalty for removing or adding a datapoint as well as a distance penalty to move to the closest datapoint. I'm struggling though, due to:
1. I need to limit each datapoint to one correct datapoint
2. Figure out which datapoint to delete if needed
3. General lack of understanding in how to implement DP algorithms
Anyone have ideas how to do this? If dynamic programming is the way to go, I'd love some link recommendation as well as some pointers in how to go about it.
Basically, you can modify the DP for Levenshtein edit distance to compute distances for your problem. The Levenshtein DP amounts to finding shortest paths in an acyclic directed graph that looks like this
*-*-*-*-*
|\|\|\|\|
*-*-*-*-*
|\|\|\|\|
*-*-*-*-*
where the arcs are oriented left-to-right and top-to-bottom. The DAG has rows numbered 0 to m and columns numbered 0 to n, where m is the length of the first sequence, and n is the length of the second. Lists of instructions for changing the first sequence into the second correspond one-to-one (cost and all) to paths from the upper left to the lower right. The arc from (i, j) to (i + 1, j) corresponds to the instruction of deleting the ith element from the first sequence. The arc from (i, j) to (i, j + 1) corresponds to the instruction of adding the jth element from the second sequence. The arc from (i, j) corresponds to modifying the ith element of the first sequence to become the jth element of the second sequence.
All you have to do to get a quadratic-time algorithm for your problem is to define the cost of (i) adding a datapoint (ii) deleting a datapoint (iii) modifying a datapoint to become another datapoint and then compute shortest paths on the DAG in one of the ways described by Wikipedia.
(As an aside, this algorithm assumes that it is never profitable to make modifications that "cross over" one another. Under a fairly mild assumption about the modification costs, this assumption is superfluous. If you're interested in more details, see this answer of mine: Approximate matching of two lists of events (with duration) .)

Find path from one city to other and then reverse with no city revisited

I found a problem on Algorithms on usaco, I cannot link to real problem as it requires authentication so pasting it.
You have just won a contest where the prize is a free vacation in Canada. You must travel via air, and the cities are ordered from east to west. In addition, according to the rules, you must start at the further city west, travel only east until you reach the furthest city east, and then fly only west until you reach your starting location. In addition, you may visit no city more than once (except the starting city, of course).
Given the order of the cities, with the flights that can be done (you can only fly between certain cities, and just because you can fly from city A to city B does not mean you can fly the other direction), calculate the maximum number of cities you can visit.
This is part of tutorial text on dynamic programming. There is suggestion for solution also given in the tutorial.
Imagine having two travelers who start in the western most city. The travelers take turns traveling east, where the next traveler to move is always the western-most, but the travelers may never be at the same city, unless it is either the first or the last city. However, one of the traveler is only allowed to make "reverse flights," where he can travel from city A to city B if and only if there is a flight from city B to city A.
It's not too difficult to see that the paths of the two travelers can be combined to create a round-trip, by taking the normal traveler's path to the eastern-most city, and then taking the reverse of the other traveler's path back to the western-most city. Also, when traveler x is moved, you know that the traveler y has not yet visited any city east of traveler x except the city traveler y is current at, as otherwise traveler y must have moved once while x was west of y.
As far as I understood the solution, I think that the solution can be done by keeping a one dimensional table for outgoing city in forward direction and a table for outgoing city in reverse direction.
eg. If I have 5 cities, A,B...E orientated in required direction and directed graph between cities is A is starting city and E is the destination.
A | B | C | D | E
A 0 | 1 | 0 | 0 | 0
B 0 | 0 | 1 | 1 | 0
C 1 | 0 | 0 | 0 | 1
D 0 | 0 | 0 | 0 | 1
E 0 | 0 | 1 | 0 | 0
I am keeping two tables one for outgoing city I will fill it by initializing first city as 1 ie. number of maximum cities visited and then for each next entry scan all the previous cities from which a path exists to the current city and then choose maximum, doing the same for reverse traveler.
table[i] = Max(j=i to 0) (table[j])
I will have maximum at the destination city, but this doesn't guarantee that any city is not repeated. If I keep one more entry in the array field along with maximum number I won't be able to switch it from forward to reverse. I am learning dynamic programming so may be I did not get correct idea.
This is the table which I constructed for the graph
A | B | C | D | E
1 | 2 | 3 | 3 | 4
1 | 1 | 2 | 1 | 3
so will take maximum from both. Please provide directions/hints so that I can proceed in right direction.
PS. this is not a homework question
Your approach with the two tables models the state for each traveler independently, as the number of cities already visited, combined with the location where that traveler is currently staying. As you found out yourself, that won't prevent visiting a city twice.
Instead, I'd use three elements to model state: the city where one traveler is currently located, the city where the other is located, and the number of cities they have visited in total, i.e. the sum of their individual counts. So you'd have a single 2d table, instead of your two 1d tables. Cell (f, r) would contain the best known number of total cities visited when the forward traveler is in city f and the reverse traveler is in city r.
You'd probably iterate over these states in order of their minimal element. That means you'll next expand a state which you have not expanded yet, and where the smaller of these two numbers is minimal among all unexpanded states. If in that state, f < r, then you'd use it to update states (f', r) with f' > r, if there is a flight from f to f'. On the other hand, if r < f you update (f, r') with r' > f and a flight from r' to r.
In pseudocode:
first = (f: 0, r: 0) # tuple with two members, called f and r
todo = set { first } # a set with a tuple as its only element
visited = a map from tuples to integers, unset values defaulting to 0
visited[first] = 1
while todo is not empty:
best = ∞
cur = null
for t in todo:
if min(t.f, t.r) < best:
best = min(t.f, t.r)
cur = t
todo.remove(cur)
if (cur.f < cur.r):
for f' in cities where flights from f arrive:
next = (f: f', r: cur.r) # keep r but use f' as the new f
todo.add(next) # will do nothing if it already is in the set
visited[next] = max(visited[next], visited[cur] + 1)
else:
for r' in cities where flights to r depart:
next = (f: cur.f, r: r')
todo.add(next)
visited[next] = max(visited[next], visited[cur] + 1)
best = 0
for cur in keys of visited:
if best < visited[cur]:
if there is a flight from cur.f to cur.r: # can close the tour
best = visited[cur]
return best

I'm trying to find if a rectangle intersects a concave polygon. Does this algorithm accomplish that?

I'm trying to find if a rectangle intersects a concave polygon. I found this algorithm:
double determinant(Vector2D vec1, Vector2D vec2){
return vec1.x*vec2.y-vec1.y*vec2.x;
}
//one edge is a-b, the other is c-d
Vector2D edgeIntersection(Vector2D a, Vector2D b, Vector2D c, Vector2D d){
double det=determinant(b-a,c-d);
double t=determinant(c-a,c-d)/det;
double u=determinant(b-a,c-a)/det;
if ((t<0)||(u<0)||(t>1)||(u>1))return NO_INTERSECTION;
return a*(1-t)+t*b;
}
If I perform this 4 times (Top to Right, Top to bottom left, top to bottom right, bottom to right) * (all edges of my polygon) would this effectively and accurately tell me if the rectangle has part of or all the concave polygon inside? If not what would be missing?
Thanks
The code attempts to find the intersection point of two segments - AB and CD.
There are many different ways to explain how it is doing it, depending on how you interpret these operations.
Let's say point A has coordinates (xa, ya), B - (xb, yb) and so on. Let's say
dxAB = xb - xa
dyAB = yb - ya
dxCD = xd - xc
dyCD = yd - yc
The the following system of two linear equations
| dxAB dxCD | | t | | xc-xa |
| | * | | = | |
| dyAB dyCD | | u | | yc-ya |
if solved for t and u, will give you the proportional position of the intersection point on line AB (value t) and on line CD (value u). These values will lie in range of [0, 1] if the point belongs to the corresponding segment and outside of that range if the point lies outside the segment (on the line containing the segment).
In order to solve this system of linear equations we can use the well-known Cramer's rule. For that we will need the determinant of
| dxAB dxCD |
| |
| dyAB dyCD |
which is exactly determinant(b - a, c - d) from your code. (Actually, what I have here is determinant(b - a, d - c), but it is not really important for the purposes of this explanation. The code you posted for some reason swaps C and D, see P.S. note below).
And we will also need determinant of
| xc-xa dxCD |
| |
| yc-ya dyCD |
which is exactly determinant(c-a,c-d) from your code, and determinant of
| dxAB xc-xa |
| |
| dyAB yc-ya |
which is exactly determinant(b-a,c-a).
Dividing these determinants in accordance with the Cramer's rule will give us the values of t and u, which is exactly what is done in the code you posted.
The code then proceeds to test the values of t and u to check if the segments actually intersect, i.e. whether both t and u belong to [0, 1] range. And if they do, it calculates the actual intersection point by evaluating a*t+b*(1-t) (equivalently, it could evaluate c*u+d*(1-u)). (Again, see the P.S. note below).
P.S. In the original code the points D and C are "swapped" in a sense that the code does c - d, where I do d - c in my explanation. But this makes no difference for the general idea of the algorithm, as long as one's careful with signs.
This swap of C and D point is also the reason for a*(1-t)+t*b expression is used when evaluating the intersection point. Normally, as in my explanation, one'd expect to see something like a*t+b*(1-t) there. (I have my doubts about this though. I would expect to see a*t+b*(1-t) there even in your version. Could be a bug.)
P.P.S. The author if the code forgot to check for det == 0 (or very close to 0), which will happen in case when the segments are parallel.
I think the following should work:
(1) for each e1 in rectangle_edges, e2 in polygon_edges
(1.1) if edgeIntersection(e1,e2) != NO_INTERSECTION
(1.1.1) return true
(2) if (max_polygon_x < max_rectangle_x) and (min_polygon_x > min_rectangle_x) and (max_polygon_y < max_rectangle_y) and (min_polygon_y > min_rectangle_y)
(2.1) return true
(2) return false
Edit: Added check for whether the polygon is inside the rectangle.
As far as I can tell after a quick glance, it tries to determine if 2 line segments intersect, and if they do, what the coordinates of the intersection point are.
No, it is not good enough to determine if your rectangle and your polygon intersect, because you'd still miss the case where either the polygon is completely inside the rectangle, or the other way around.

Resources