So I'm trying to use a modified Bellman Ford algorithm to find the shortest path from the starting vertex to the ending vertex but I cannot go over a certain distance. So given a graph with edges:
0 1 100 30
0 4 125 50
1 2 50 250
1 2 150 50
4 2 100 40
2 3 90 60
4 3 125 150
Where the each line represents an edge and the first value is the starting vertex, the second value is the end vertex, the third is cost and the fourth is the distance.
With the code I have now when I try to find the cheapest path from 0 to 3 without going over 140 it yields 0 (default when no path is found) instead of 340 (the cost of the cheapest path). Any suggestions on how to alter my code.
Just gonna copy the code down below because this site is not letting me do anything else.
static void BellmanFord(struct Graph *graph, int source, int ending, int max){
int edges = graph->edgeCount;
int vertices = graph->verticesCount;
int* money = (int*)malloc(sizeof(int) * vertices);
int* distance = (int*)malloc(sizeof(int) * vertices);
for (int I = 0; I < vertices; I++){
distance[I] = INT_MAX;
money[I] = INT_MAX;
}
distance[source] = 0;
money[source] = 0;
for (int I = 1; I <= vertices - 1; ++I){
for int j = 0; j < edges; ++j){
int u = graph->edge[j].Source;
int v = graph->edge[j].Destination;
int Cost = graph->edge[j].cost;
int Duration = graph->edge[j].duration;
if ((money[u] != INT_MAX) && (money[u] + Cost < money[v])){
if (distance[u] + Duration <= max){
money[v] = money[u] + Cost;
distance[v] = distance[u] + Duration;
}
}
}
}
if (money[ending] == INT_MAX) cout << "0" << endl;
else cout << money[ending] << endl;
}
Please help! This is probably not that hard but finals are stressing me out
This problem, known as the "constrained shortest path" problem, is much harder to solve than this. The algorithm you provided does not solve it, it only might catch the solution, only by luck, according to the graph's structure.
When this algorithm is applied on the graph you provide, with max-distance = 140, it fails to find the solution, which is 0-->1-->2-->3 (using the edge 1 2 150 50) with total cost of 340 and a distance of 140.
We can observe the reason of failure by logging the updates to the nodes whenever they are updated, and here is the result:
from node toNode newCost newDistance
0 1 100 30
0 4 125 50
1 2 250 80
4 2 225 90
Here the algorithm is stuck and cannot go further, since any progress from this point will lead to paths that exceed the max distance (of 140). As you see, node 2 has found the path 0-->4--2 which is the lowest-cost from node 0 while respecting the max-distance constraint. But now, any progress from 2 to 3 will exceed the distance of 140 (it will be 150, because 2->3 has a distance of 60.)
Running again with max-distance=150 will find the path 0-->4->3 with cost 315 and distance 150.
from node toNode newCost newDistance
0 1 100 30
0 4 125 50
1 2 250 80
4 2 225 90
2 3 315 150
Obviously this is not the minimum cost path that respects the constraint of distance; the correct should be the same (that it failed to find) in the first example. This again proves the failure of the algorithm; this time it gives a solution but which is not the optimal one.
In conclusion, this is not a programming mistake or bug in the code, it is simply that the algorithm is not adequate to the stated problem.
Okay so right before the
if (money[ending] == INT_MAX) cout << "0" << endl;
I added some code that made it work but I'm wondering will this work for every case or does it need to be altered a little.
if (money[ending] == INT_MAX){
for (int j = 0; j < edges; ++j){
int u = graph->edge[j].Source;
int v = graph->edge[j].Destination;
int Cost = graph->edge[j].cost;
int Duration = graph->edge[j].duration;
if ((distance[u] != INT_MAX) && (distance[u] +Duration < distance[v])){
if (distance[u] + Duration <= max){
money[v] = money[u] + Cost;
distance[v] = distance[u] + Duration;
}
}
}
}
Related
Various signal towers are present in a city.Towers are aligned in a straight horizontal line(from left to right) and each tower transmits a signal in the right to left direction.Tower A shall block the signal of Tower B if Tower A is present to the left of Tower B and Tower A is taller than Tower B. So,the range of a signal of a given tower can be defined as :
{(the number of contiguous towers just to the left of the given tower whose height is less than or equal to the height of the given tower) + 1}.
#include <iostream>
#include <vector>
using namespace std;
vector<int> res;
void recursion(int a[],int x)
{
if (x >= 0)
{// Taking the last element of the array as the max element
int max = a[x], count = 0;
for (int i = x; i >= 0; i--)
{//Comparing the max with all the elements in the array
if (max >= a[i])
{
count++;
}
else
{
break;
}
}
//Pushing the count of the current element in the vector.
res.push_back(count);
x = x - 1;
recursion(a, x);
}
}
int main() {
int TestCase, n;
cin >> TestCase;
for (int l = 0; l < TestCase; l++)
{
cin >> n;
int * arr = new int[n];
//Getting the elements
for (int j = 0; j < n; j++)
{
cin >> arr[j];
}
recursion(arr, n-1);
//Iterating through the vector in reverse manner and printing
//the result.
for (auto it = res.rbegin(); it != res.rend(); ++it)
{
cout << *it << " ";
}
delete[] arr;
}
return 0;
}
First line contains an integer T specifying the number of test cases.
Second line contains an integer n specifying the number of towers.
Third line contains n space separated integers(H[i]) denoting the height
of each tower.
Print the range of each tower (separated by a space).
Sample Input:
1
7
100 80 60 70 60 75 85
Sample Output:
1 1 1 2 1 4 6
My solution is correct but the time complexity is the issue. Is there any way to reduce time complexity?
To calculate the range of each tower which emits signals to the left, you need to use a stack structure.
We go from left to right in the array and we will store each element in the stack. Now, we insert towers in the stack.
Whenever we get to the next tower, we keep popping towers from the stack whose height is less than the current tower. Once done, we will insert the current tower in the stack and so on for subsequent towers.
Important thing to note here is that you will need to store the no. of towers beaten by the current tower too when you insert them in the stack.
Answer for each tower(Except the base case) is no. of towers beaten + 1.
The integer inside {} below is the no. of towers beaten by the current tower.
Example:
100 80 60 70 60 75 85
^
Stack is empty when we are at 100, so we insert it into the stack and print answer for it as 1 considering that as the base answer.
Current stack: 100{0}
80 60 70 60 75 85
^
Now, let's test for 80. When tower 80 emits signals to the left, we keep pooping all elements from the stack which are less than 80 and stop when we get a block(that is, a tower with same or higher height). In this case, we stop at 100 itself. So, the distance covered by the signal is 1.
Current stack: 100{0} 80{0}
60 70 60 75 85
^
Now, the answer for 60 is 1 again.
Current stack: 100{0} 80{0} 70{1}
70 60 75 85
^
For 70, signals beat 60 and stop at 80, so answer for 70 is no. of towers beaten + 1, so 1 + 1 = 2.
Current stack: 100{0} 80{0} 70{1} 60{0}
60 75 85
^
60 beats nobody, so 0 + 1 = 1.
Current stack: 100{0} 80{0} 75{3}
75 85
^
75 beats 60 and 70, but we get 3 towers beaten since we add no. of towers beaten by the smaller towers + that tower itself as well. So, to put it in simple words,
60{0} is 1(60 itself) + 0(no. of towers beaten by 60 itself) + 1 (70 itself) + 1(no. of towers beaten by 70 itself) = 1 + 1 + 1 = 3. Answer for 75 is 3 + 1 = 4.
Current stack: 100{0} 85{5}
85
^
Answer for 85 is 5 + 1 = 6 => 1(of 75) + 3(of 75 beats) + 1(of 80) + 0 (of 80 beats).
Hope this answers your question.
int f(const std::vector<int>& v) {
int result = 0;
for (int i = 0; i < v.size(); ++i) { O(N)
for (int j = v.size(); j >= 0; j -= 2) { O(N/2)
result += v.at(i) * j;
}
}
return result;
}
The inner for loop is O(N/2), however I am wondering why this is because
For example, if v.size() is 10, then
10 >= 0 ✓
8 >= 0 ✓
6 >= 0 ✓
4 >= 0 ✓
2>= 0 ✓
0 >= 0 ✓
-2 Fails
The inner for loop could be executed 6 times with an input size of 10
What am I missing?
EDIT* I understand that only highest magnitude is taken into consideration. This question was more about coming up with the original O(N/2 + 1)
Complexity gives you a way to assess the magnitude of time it would take an input of certain size to complete, not the accurate time it would perform with.
Therefore, when dealing with complexity, you should only consider the highest magnitude, without constant multipliers:
O(N/2 + 1) = O(N/2) = O(N)
In a comment, you said:
I understand this, but I am just curious as to how O(N/2) is obtained
Take a look at the following table:
Size of vector Number of time the inner loop is executed:
0 1
1 1
2 2
3 2
...
100 51
101 51
...
2x x + 1
2x + 1 x + 1
If you take the constant 1 out of that equation, the inner loop is O(N/2).
I am writing a program for card games. There can be several game players (say, from 2 to 7). A deck consists of 54 cards. I need to distribute/deal cards to the players randomly.
We can consider the deck of 54 cards as a char array of 54 elements. Let us suppose that in a certain game each player must be given with 6 cards. The number of players is 2. So, it is necessary to generate two arrays, each of them consists of 6 elements selected from a "big" array of 54 elements. Moreover, in those two generated arrays there should not be shared/duplicate elements.
I tried a recursive algorithm to obtain a sequence of m unique random numbers from 0 to (m - 1).
X(n+1) = (a * X(n) + c) mod m
You need to set the parameters:
m -- module, m > 0
a -- factor, 0 <= a < m
c -- increment, 0 <= c < m
X(0) -- initial value , 0 <= X(0) < m
Numbers c and m must be coprime.
(a - 1) is divisible by p for each prime p that is a divisor of m
If m is divisible by 4 then (a - 1) must be divisible by 4.
Here's the code for this algorithm. As you can see, the parameters a, c, m and X(0) satisfy the mentioned conditions.
int a = 13,
c = 11,
m = 54, // because the total number of cards is 54
x0 = 1;
int x[100];
x[0] = x0;
cout << x[0] << " ";
for (int i = 1; i < m; i++)
{
x[i] = (a * x[i - 1] + c) % m;
cout << x[i] << " ";
}
The result is: 1 24 53 52 39 32 49 0 11 46 15 44 43 30 23 40 45 2 37 6 35 34 21 14 31 36 47 28 51 26 25 12 5 22 27 38 19 42 17 16 3 50
13 18 29 10 33 8 7 48 41 4 9 20. Do you think it is random?
What can you say about this algorithm? In general, what should be the idea of a random distribution of cards for each player?
You see, if I integrate this algorithm to my program, it will deal the same sequence of cards as it is shown above each time you launch the program (because the parameters do not change). So I will need to change a, m, c and X(0) between launches of my program. Then I will have another problem: how to set these parameters automatically (and randomly, too) so that they satisfy the necessary conditions (see the bulleted list above).
It seems to me like you're making an unnecessarily complex system.
A much simpler approach is to create an array of all of your elements, shuffle it, and then just remove elements one at a time.
A simple and efficient way of shuffling is to use a Fisher-Yates shuffle:
//Initialize an array/vector/etc. with all the possible values
for (int i = NUMBER_OF_ELEMENTS-1; i >= 0; i--)
{
//Pick a random integer j between 0 and i (inclusive)
//Swap elements i and j
}
Now, you can just iterate through the shuffled array, picking the next element every time you need a new card.
int pos = 0; //The position of the next card in the deck
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < NUMBER_OF_PLAYERS; j++)
{
player[j].addCard(deck[pos++])
}
}
Ideally, you would probably want to wrap some of this into classes, but I've left that out for brevity.
You cannot guarantee randomness the way you put it. It is a generated sequence with low informational enthropy - in other words it is easily hacked.
You can simply use standard rand() from stdlib http://www.cplusplus.com/reference/cstdlib/rand/.
I'd recommend using mt19937 comes with std in c++11 http://www.cplusplus.com/reference/random/mt19937/ or boost one as mentioned in comments.
another way to do it, could be to randomize the action of taking a card instead of a shuffle the container.
something like this :
// first step
// init and fill container
std::vector<int> v;
for (int i = 0; i < 54; ++i)
v.push_back(i);
// second step
// take a random card
srand(time(NULL)); // init seed
int i = std::rand() % v.size();
int card = v[i]; // get card
v.erase(vec.begin() + i); // remove card from deck
return card;
for the second step, you need <ctime> and <cstdlib>. I am not sure it is better than the other solution. Just my two cents.
I'm making a program where I have a list of 34 cities and I am wanting to give each of these cities a probability of being chosen.
So I have:
vector<float> vec;
int s;
cin >> s;
srand(s);
for (int k=0; k < 34; k++)
{
float p1= (float)rand()/(float)((unsigned)RAND_MAX+1);
vec.push_back(p1);
}
So that gives each city a probability. The problem I am now having is I want to then do a random number generator that will choose two of these cities. So, for example city1 will have a 5%, city2 a 2%, city3, a 3%, etc. How can I randomly choose two of these cities based off the probabilities given?
I did this in genetic algorithm.
for your cities consider a line of 10 units.
now from 0-5 units on line are city1 6-7 for city2 and 8-9 for city3.
now choose a number at random from 0-9.
and found out in which cities range it comes in.
At first glance my solution will be :
Create a number equals to all city's probability
Create a random number, with max random number is equal to the previous number
Take the random number, and go throught your city vector and take the one who is corresponding.
Example :
City 1 : 5%
City 2 : 8%
City 3 : 2%
City 4 : 5%
City 5 : 12%
Create a number -> Number a = 32 (5+8+2+5+12)
Generate a number with : 1 <= number
Assume that the number is equal to 12
City 1 is choose if : 1 <= number <= 5 (So not)
City 2 is choose if : 6 <= number <= 13 (So yes)
City 2 is choose.
If you have any questions about that, you are welcome :)
Edit :
Well i will give you some more explaination.
Take this code :
for (int k=0; k < 10; k++)
{
float p1= (float)rand()/(float)((unsigned)RAND_MAX+1);
vec.push_back(p1);
}
Assume now that vec contain the following informations :
5
3
8
5
12
14
8
5
6
18
With each number correspond to the probability to choose a city.
5 -> 5% probability to choose (City1)
3 -> 3% probability to choose (City2)
8 -> 8% probability to choose (City3)
... etc
Now i will give you some code and i will explain it :
int nbReference = 0;
for (auto it = vec.begin() ; it != vec.end() ; ++it)
{
nbReference += *it;
}
nbReference = rand(nbReference);
int i = 0;
int cityProbability = 0;
for (auto it = vec.begin() ; it != vec.end() ; ++it)
{
cityProbability = *it;
if ((i + cityProbability) > nbReference)
{
return (i + 1);
}
i += cityProbability;
}
First i create a number equals to the addition of all city's probability
int nbReference = 0;
for (auto it = vec.begin() ; it != vec.end() ; ++it)
{
nbReference += *it;
}
Second, i generate a number that is respect the following range -> 0 < nbReference
Third, i create a loop that take all city one by one and quit when we got right city.
How does we know when a city is good?
Let's take an example!
With our previous probability
5 3 8 5 12 14 8 5 6 18
NbReference is equals to (5+3+8+5+12+14+8+5+6+18) so 84
To each city we are going to put a range equals to his probability plus all of previous city's probability. Let me show you :
5 -> Range 0 to 4 (0 to 4 = 5 ---> 5%)
3 -> Range 5 to 8 (5 to 8 = 3 ---> 3%)
8 -> Range 9 to 17
5 -> Range 18 to 22
... etc
If the number that we create here
nbReference = rand(nbReference);
Is in a city range, so that city is choosed.
Example : If the number is 16, city3 is choosed!
5 -> Range 0 to 4 Number is 16 so NOPE
3 -> Range 5 to 8 Number is 16 so NOPE
8 -> Range 9 to 17 Number is 16 so YES!
5 -> Range 18 to 22
... etc
Does is this helpfull? :)
Any questions? You are welcome
Maybe this code can help you (follows partially WhozCraig advice)
#include <iostream>
#include <random>
#include <algorithm>
int main(int argc, const char * argv[])
{
using namespace std::chrono;
system_clock::time_point tp = system_clock::now();
system_clock::duration dtn = tp.time_since_epoch();
std::default_random_engine generator(static_cast<int>(dtn.count()));
//Generate 34 cities
std::uniform_real_distribution<double> gen_distribution(0,1);
auto getProb = std::bind ( gen_distribution, generator );
std::vector<double> citiesProb;
double probSum(0.0);
double cityProb(0.0);
for (int k=0; k < 34; k++)
{
cityProb = getProb();
probSum += cityProb;
citiesProb.push_back(cityProb);
}
//Pick 7 cities
std::uniform_real_distribution<double> pick_distribution(0,probSum);
auto pickCity = std::bind ( pick_distribution, generator );
double chooseCity;
double probBasket;
for (int k=0; k < 7; ++k)
{
probBasket = 0.0;
chooseCity = pickCity();
for (int i = 0; i < citiesProb.size(); ++i)
{
if (chooseCity >= probBasket && chooseCity < probBasket + citiesProb[i])
{
std::cout << "City with index " << i << " picked" << std::endl;
}
probBasket += citiesProb[i];
}
}
return 0;
}
How it works:
city1 5%(0.05), city2 25%(0.25), city3 8%(0.08), city4 10%(0.1)
then
probSum = 0.05 + 0.25 + 0.08 + 0.1 = 0.48
then choose a number between 0 and 0.48 (named pickProb) and
if pickProb is between 0 and 0.05 pick city1 (prob = 0.05/0.48 = 10%)
if pickProb is between 0.05 and 0.30 pick city2 (prob = 0.25/0.48 = 52%)
if pickProb is between 0.30 and 0.38 pick city3 (prob = 0.08/0.48 = 16%)
if pickProb is between 0.38 and 0.48 pick city4 (prob = 0.1/0.48 = 20%)
if probSum = 1.0 then city1 is picked with probability 5%, city2 is picked with probability 25% and so on.
So I'm trying to make a graphing application, and I'm using Desmos as a base for that.
The thing I'm struggling with is the way Desmos handles the subdivisions of the axes. When you zoom in or out the scales are always on "easy" simple numbers like 5, 100, 1000 etc. So my question is: how does one go about simplifying their scale with any level of zoom?
BTW: Using C++
I was going to write a description of how to do this in general, but then I realize that the code may be easier than explaining.
Most important step: define precisely what you mean by "easy simple" numbers.
Example #1: 1, 2, 4, 8, 16, 32, 64, 128, ... , 1073741824, ...
These are powers of two. So, a straightforward ceil(log(x)/log(2.0)) will solve it.
Example #2: 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, ...
There is a mixture of powers of two, and some multiples of it. Let's take a closer look.
A subset of these can be described as powers of ten.
Changing the formula to ceil(log(x)/log(10.0)) will solve it.
For each power-of-ten, its multiples by 2.0 and 5.0 are also "easy simple numbers".
Inside each iteration, after checking the power-of-ten value, also check the two multiples. If it fits inside one of the multiple, that value can be returned as result.
Code
The following code is only meant to explain the concept. It is not efficient - an efficient version should have used logarithm to get the result in O(1) time.
#include <iostream>
#include <vector>
#include <limits>
#include <stdexcept>
#include <algorithm>
using namespace std;
double getNiceAxisLength(double value, double baseLength, double step, const std::vector<double>& subSteps)
{
typedef std::vector<double>::const_iterator VecDoubleIter;
if (value < 0.0)
{
throw std::invalid_argument("Error: value must be non-negative. Take absolute value if necessary.");
}
if (baseLength <= 0.0)
{
throw std::invalid_argument("Error: baseLength must be positive.");
}
if (step <= 1.0)
{
throw std::invalid_argument("Error: step must be strictly greater than 1.");
}
for (VecDoubleIter iter = subSteps.begin(); iter != subSteps.end(); ++iter)
{
double subStep = *iter;
if (subStep <= 1.0 || subStep >= step)
{
throw std::invalid_argument("Error: each subStep must be strictly greater than 1, and strictly smaller than step.");
}
}
// make ascending.
std::vector<double> sortedSubSteps(subSteps.begin(), subSteps.end());
std::sort(sortedSubSteps.begin(), sortedSubSteps.end());
if (value <= baseLength)
{
return baseLength;
}
double length = baseLength;
double terminateLength = numeric_limits<double>::max() / step;
while (length < terminateLength)
{
for (VecDoubleIter iter = sortedSubSteps.begin(); iter != sortedSubSteps.end(); ++iter)
{
double subStep = *iter;
if (value <= length * subStep)
{
return (length * subStep);
}
}
double nextLength = length * step;
if (value <= nextLength)
{
return nextLength;
}
length = nextLength;
}
return baseLength;
}
int main()
{
double baseLength = 1.0;
double step = 10.0;
std::vector<double> subSteps;
subSteps.push_back(2.5);
subSteps.push_back(5);
for (int k = 0; k < 1000; k += ((k >> 2) + 1))
{
double value = k;
double result = getNiceAxisLength(value, baseLength, step, subSteps);
cout << "k: " << value << " result: " << result << endl;
}
cout << "Hello world!" << endl;
return 0;
}
Output
k: 0 result: 1
k: 1 result: 1
k: 2 result: 2.5
k: 3 result: 5
k: 4 result: 5
k: 6 result: 10
k: 8 result: 10
k: 11 result: 25
k: 14 result: 25
k: 18 result: 25
k: 23 result: 25
k: 29 result: 50
k: 37 result: 50
k: 47 result: 50
k: 59 result: 100
k: 74 result: 100
k: 93 result: 100
k: 117 result: 250
k: 147 result: 250
k: 184 result: 250
k: 231 result: 250
k: 289 result: 500
k: 362 result: 500
k: 453 result: 500
k: 567 result: 1000
k: 709 result: 1000
k: 887 result: 1000
Hello world!
Hello world!