Breadth First Traversal Algorithm - c++

For a given n, I am trying to find the smallest number that is divisible by n, and also has sum of digits as n.
For example: For n = 10, Output should be 190, For n = 11, Output should be 209
I have adopted the Breadth First Traversal Approach to solve my problem.
#include <iostream>
#include <queue>
#include <string>
using namespace std;
class State{
public:
int sum,rem;
string str;
State(int s,int r,string st){
sum = s;
rem = r;
str = st;
}
};
int main() {
int n,newSum,newRem;
queue<State> q;
cin>>n;
bool visited[n+1][n+1] = {0};
State curr = State(0,0,"");
q.push(curr);
visited[0][0] = 1;
while(!q.empty()){
curr = q.front();
q.pop();
if(curr.sum==n && curr.rem==0){
cout<<curr.str<<endl;
break;
}
for(int j=0; j<=9; j++){
newSum = curr.sum + j;
newRem = (curr.rem*10+j)%n;
if(newSum > n){
break;
}
else if(!visited[newSum][newRem]){
curr = State(curr.sum+j, ((curr.rem*10)+j)%n,curr.str+to_string(j));
q.push(curr);
visited[newSum][newRem] = 1;
}
}
}
return 0;
}
My code, returns a number that satisfies the condition, but it is not the smallest possible number.
For n = 10, my code gives 12340
For n = 11, my code gives 1010207
Ideone link: http://ideone.com/c4W48N

You should try running through with a debugger, it shows up the problem very quickly.
In this line:
curr = State(curr.sum+j, ((curr.rem*10)+j)%n,curr.str+to_string(j));
q.push(curr);
You are assigning a new value to the curr variable, which you are then using next time around the loop. This means instead of trying 1, 2, 3, etc, you are trying 1, 12, 123, etc.
You are also recalculating items you have just calculated.
You can replace this with
State newState = State(newSum, newRem, curr.str + to_string(j));
q.push(newState);
or more simply again:
q.push(State(newSum, newRem, curr.str+to_string(j)));

Related

Efficiently find the nth number in a series where the numbers are only divisible by 2,3 and 5

I want to find the nth number in a series of numbers only divisible by 2, 3 and 5 and not divisible by any other primes.
Here is the simplest solution that I have for finding the 1500th number. This takes about 16 seconds to execute. I want to know if there is a way to make it any faster like maybe using multi threading.
#include <iostream>
using namespace std;
int main()
{
int temp, seriesCounter = 1, currentNumber = 2;
while (seriesCounter < 1500)
{
temp = currentNumber;
//Remove all multiple of 2
while (temp % 2 == 0)
{
temp /= 2;
}
//Remove all multiple of 3
while (temp % 3 == 0)
{
temp /= 3;
}
//Remove all multiple of 5
while (temp % 5 == 0)
{
temp /= 5;
}
// If only 1 remains, the number is valid, else not.
if (temp == 1)
{
seriesCounter++;
}
currentNumber++;
}
cout << "The 1500th number in the series is : " << --currentNumber << endl << endl;
return 1;
}
Here's one pretty straightforward approach. It finds 1500th element in under a second (I didn't bother to measure more precisely).
#include <set>
#include <iostream>
int main() {
int n = 1500;
std::set<long long> s;
s.insert(2);
s.insert(3);
s.insert(5);
long long num = 0;
while (n--) {
num = *s.begin();
s.erase(s.begin());
s.insert(num*2);
s.insert(num*3);
s.insert(num*5);
}
std::cout << num;
}
Fast solution done in 0.000031s on a i7 laptop (result: num[1499]=860934420):
Time complexity is O(n) (n=1500 in your case). assume the current sequence is num[]. we want to grow it to 1500 elements. the main idea is to keep a record of three locations in the sequence num[], let's call them idx[0], idx[1] and idx[3]. so that 2num[idx[0]], 3num[idx[1]], and 5*num[idx[2]] becomes just >= the last number in sequence(num.back()). then add the smallest of the three to the end of the sequence (which becomes the new num.back()).
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
using std::vector;
using namespace std::chrono;
int main()
{
auto start = high_resolution_clock::now();
const vector<int> p{ 2,3,5 };
vector<int> idx{ 0,0,0 };
vector<int> num = { 2,3,4,5 }; num.reserve(1500);
vector<int> candidate(3);
while (num.size() < 1500) {
int candidate = INT_MAX;
for (int i = 0; i < p.size(); i++) {
int t;
while (num.back() >= (t=num[idx[i]] * p[i])) idx[i]++;
candidate = std::min(candidate, t);
}
num.push_back(candidate);
}
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
std::cout << num.back();
std::cout <<"\ntakes "<< duration.count() << " microseconds";
}
The code can further be improved. The idea is the same, but the number of multiplication performed is reduced, by remembering the multiplication result in array candidate[3]:
const vector<int> p{ 2,3,5 };
vector<int> idx{ 1,0,0 };
vector<int> num = { 2,3,4,5 }; num.reserve(1500);
vector<int> candidate{ 6,6,10 };
while (num.size() < 1500) {
auto it = std::min_element(candidate.begin(), candidate.end());
if (num.back() != *it) num.push_back(*it);
int which_p = it - candidate.begin();
*it = num[++idx[which_p]] * p[which_p];
}

How to find all possible combinations of adding two variables, each attached to a multiplier, summing up to a given number (cin)?

In my situation, a lorry has a capacity of 30, while a van has a capacity of 10. I need to find the number of vans/lorries needed to transport a given amount of cargo, say 100. I need to find all possible combinations of lorries + vans that will add up to 100.
The basic math calculation would be: (30*lorrycount) + (10*vancount) = n, where n is number of cargo.
Output Example
Cargo to be transported: 100
Number of Lorry: 0 3 2 1
Number of Van: 10 1 4 7
For example, the 2nd combination is 3 lorries, 1 van. Considering that lorries have capacity = 30 and van capacity = 10, (30*3)+(10*1) = 100 = n.
For now, we only have this code, which finds literally all combinations of numbers that add up to given number n, without considering the formula given above.
#include <iostream>
#include <vector>
using namespace std;
void findCombinationsUtil(int arr[], int index,
int num, int reducedNum)
{
int lorry_capacity = 30;
int van_capacity = 10;
// Base condition
if (reducedNum < 0)
return;
// If combination is found, print it
if (reducedNum == 0)
{
for (int i = 0; i < index; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
// Find the previous number stored in arr[]
// It helps in maintaining increasing order
int prev = (index == 0) ? 1 : arr[index - 1];
// note loop starts from previous number
// i.e. at array location index - 1
for (int k = prev; k <= num; k++)
{
// next element of array is k
arr[index] = k;
// call recursively with reduced number
findCombinationsUtil(arr, index + 1, num,
reducedNum - k);
}
}
void findCombinations(int n)
{
// array to store the combinations
// It can contain max n elements
std::vector<int> arr(n); // allocate n elements
//find all combinations
findCombinationsUtil(&*arr.begin(), 0, n, n);
}
int main()
{
int n;
cout << "Enter the amount of cargo you want to transport: ";
cin >> n;
cout << endl;
//const int n = 10;
findCombinations(n);
return 0;
}
Do let me know if you have any solution to this, thank you.
An iterative way of finding all possible combinations
#include <iostream>
#include <vector>
int main()
{
int cw = 100;
int lw = 30, vw = 10;
int maxl = cw/lw; // maximum no. of lorries that can be there
std::vector<std::pair<int,int>> solutions;
// for the inclusive range of 0 to maxl, find the corresponding no. of vans for each variant of no of lorries
for(int l = 0; l<= maxl; ++l){
bool is_integer = (cw - l*lw)%vw == 0; // only if this is true, then there is an integer which satisfies for given l
if(is_integer){
int v = (cw-l*lw)/vw; // no of vans
solutions.push_back(std::make_pair(l,v));
}
}
for( auto& solution : solutions){
std::cout<<solution.first<<" lorries and "<< solution.second<<" vans" <<std::endl;
}
return 0;
}
We will create a recursive function that walks a global capacities array left to right and tries to load cargo into the various vehicle types. We keep track of how much we still have to load and pass that on to any recursive call. If we reach the end of the array, we produce a solution only if the remaining cargo is zero.
std::vector<int> capacities = { 30, 10 };
using Solution = std::vector<int>;
using Solutions = std::vector<Solution>;
void tryLoad(int remaining_cargo, int vehicle_index, Solution so_far, std::back_insert_iterator<Solutions>& solutions) {
if (vehicle_index == capacities.size()) {
if (remaining_cargo == 0) // we have a solution
*solutions++ = so_far;
return;
}
int capacity = capacities[vehicle_index];
for (int vehicles = 0; vehicles <= remaining_cargo / capacity; vehicles++) {
Solution new_solution = so_far;
new_solution.push_back(vehicles);
tryLoad(remaining_cargo - vehicles * capacity, vehicle_index + 1, new_solution, solutions);
}
}
Calling this as follows should produce the desired output in all_solutions:
Solutions all_solutions;
auto inserter = std::back_inserter(all_solutions)
tryLoad(100, 0, Solution{}, inserter);

How can I find the maximum element in the left and right sides of an array?

I have a homework problem in C++ that I could (and did) solve, but not fast enough.
So the problem goes like this: On a platform, there are n bars of equal width and height. It starts raining. Find out the quantity of water that fits in between the bars (Very bad enunciation , I know, it's better to look at the example). Examples:
n = 6
bar lengths = {3, 0, 0, 2, 0, 4}
Answer would be = 10
The cubes of water would "fill out" the empty space between the bars and I need the find the number of cubes:
Explanation:
Another example:
n = 12
bar lengths = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}
Answer = 6
What I tried:
For each spot in the array, I found the maximum height bar to the left of it and to the right of it and then I "filled" this spot with the minimum between the maximum to the left and the maximum to the right minus the height of the bar at the present spot:
#include <iostream>
using namespace std;
int main() {
int n, a[100001], i, j, volume=0, max_left, max_right;
cin >> n;
// Input the array
for (i=0; i<n; i++) {
cin >> a[i];
}
// For each element (except the first and last)
for (i=1; i<(n-1); i++) {
max_left = max_right = a[i];
// Find the maximum to the left of it and to the right of it
for (j=0; j<i; j++) {
if (a[j] > max_left) {
max_left = a[j];
}
}
for (j=(i+1); j<n; j++) {
if (a[j] > max_right) {
max_right = a[j];
}
}
// The quantity of water that fits on this spot is equal to
// the minimum between the maxes, minus the height of the
// bar in this spot
volume += (min(max_left, max_right) - a[i]);
}
cout << volume;
return 0;
}
The solution is good, I get the corrent results. But the speed is a problem. I believe the complexity of this solution is O(n^2), if I'm not mistaken. Now the problem has to be solved in O(n). The problem is: How can I find the maxes in both directions for each element in O(n)? Any help will be appreciated. Thanks!
Find the highest bar in the complete list. This gives to sub-ranges Before and After (both excluding the highest bar).
Iterate over both sub-ranges (front to back for Before, back to front for After): Remember the highest bar you've found on the way, starting with 0. Add the difference of the current height to the result.
Add both results.
This works because once you've found the overall maximum height, all other heights for Front and Back are at least lower or equal than the maximum. This way you can skip searching in both directions and simply use the highest bar you've met so far.
Both steps are O(n). Here is an example:
#include <algorithm>
#include <cassert>
#include <iostream>
#include <numeric>
#include <vector>
template <typename First, typename Last>
int calcRange(First begin, Last end) {
int max{0};
int result{0};
for (auto it = begin; it != end; ++it) {
const auto current = *it;
result += std::max(0, max - current);
max = std::max(max, current);
}
return result;
}
int calc(const std::vector<int>& bars) {
if (bars.size() <= 1) return 0;
// find max = O(n)
const auto maxIt = std::max_element(bars.cbegin(), bars.cend());
assert(maxIt != bars.cend());
// calculate left and right = O(n)
const auto l = calcRange(bars.cbegin(), maxIt);
const auto r = calcRange(bars.crbegin(), std::make_reverse_iterator(maxIt));
return l + r;
}
int main() {
std::cout << calc({3, 0, 0, 2, 0, 4}) << std::endl;
std::cout << calc({0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}) << std::endl;
}
I have to say, that I really liked this question.
This might give you an idea on how to solve this question. Basically, you are looking to leftmost and rightmost bar heights. Then you will raise the waterlevel to the minimum of both and compute the amount of water needed for this. Afterwards you can shrink the bars array and repeat the process.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
int main() {
std::vector<int> bars{ 3, 0, 0, 2, 0, 4 };
int waterCounter = 0;
int waterLevel = 0;
auto leftIter = bars.begin();
auto rightIter = bars.end() - 1;
while (true)
{
if (leftIter == rightIter) break;
auto newWaterLevel = std::min(*leftIter, *rightIter);
if (newWaterLevel > waterLevel)
{
auto newRight = std::next(rightIter);
auto size=std::distance(leftIter, newRight);
auto waterInGaps = 0;
for (auto iter=leftIter; iter!=newRight; iter++ )
{
waterInGaps += *iter > newWaterLevel ? 0 : newWaterLevel-*iter;
*iter = *iter>newWaterLevel?*iter:newWaterLevel;
}
waterCounter += waterInGaps;
}
while (leftIter!=rightIter)
{
if (*leftIter > newWaterLevel) break;
std::advance(leftIter, 1);
}
while (rightIter!=leftIter)
{
if (*rightIter > newWaterLevel) break;
std::advance(rightIter, -1);
}
waterLevel = newWaterLevel;
}
std::cout << waterCounter << std::endl;
return EXIT_SUCCESS;
}
Thanks a lot everyone, your ideas helped! As I am not that advanced, I couldn't (and didn't really know how to) use vectors, auto (this one seems like magic to me), templates and other things. If anyone is still interested, this is the code I used and I got 100 points on the site:
#include <iostream>
using namespace std;
int main()
{
int n, a[100001], left_max[100001], right_max[100001];
int i, max_to_right, max_to_left, volume=0;
cin >> n;
for (i=0; i<n; i++) {
// Input the array
cin >> a[i];
// Directly find the "maximum to the left" of each element
if (i == 0) {
left_max[i] = max_to_left = a[i];
}
else {
if (a[i] > max_to_left) {
max_to_left = a[i];
}
left_max[i] = max_to_left;
}
}
// Not the only thing left is to find the "maximum to the right" of each element
for (i=(n-1); i>=0; i--) {
if (i == (n-1)) {
right_max[i] = max_to_right = a[i];
}
else {
if (a[i] > max_to_right) {
max_to_right = a[i];
}
right_max[i] = max_to_right;
}
// No need to have another loop afterwards, add to volume as we go
if (i>0 && i<(n-1)) {
volume += (min(left_max[i], right_max[i]) - a[i]);
}
}
cout << volume;
return 0;
}
I basically did the same thing, but faster. I found the maximum to the right and to the left of each element, but I found the maximum to the left of each element while reading the input and then with another loop I found the maximum of each element, but to the right. The website had a very similar solution, just a bit shorter.
I would start off by asking off a few questions which would get me close to a solution. Think of it this way, if you poured water into the structure above, the empty spots would only ever accumulate to the right or the left of the 'Highest bar'. Once you have that insight, now from left to the highest bar do the following, currbar_from_left = -1 and the current value set to start of the array.
1- if the currbar_from_left > current then currbar_from_left = current
else ans = ans + (currbar - currbar_from_left) - add the difference to the answer since we know definately that this would accmulate compared to our anchor point(the highest bar)
2- now do another traversal, this time from right of the array to the highest point. currbar_from_right = -1 and current set to the last value in the array
if the currbar_from_right > current then currbar_from_right = current
else ans = ans + (currbar - curbar_from_right)
3- The ans is now the total empty cubes.
You could combine steps 1 and 2 into a single loop with the conditions as they are but the above algorithm is more clear in terms of understanding.
The following code demostrates this:
int n, a[100001], i, j, volume = 0, max_left, max_right;
cin >> n;
// Input the array
for (i = 0; i<n; i++) {
cin >> a[i];
}
// Maximum height in the array
int maximum_bar = -1, maximum_index = -1;
for (i = 0; i < n; i++) {
if (a[i] > maximum_bar)
{
maximum_bar = a[i];
// where did i see it?
maximum_index = i;
}
}
//Left search, to the maximum_bar
int left = -1;
for (i = 0; i < maximum_index; i++) {
if (a[i] > left) left = a[i];
else volume = volume + (left - a[i]);
}
//Right search, to the maximum_bar
int right = -1;
for (i = n - 1; i >= maximum_index; i--) {
if (a[i] > right) right = a[i];
else volume = volume + (right - a[i]);
}
cout << volume;
return 0;
Let's try a different approach. We can do this in a single pass from left to right, except for a special case at the end of the array.
Consider that we're iterating from left to right, keeping track of what's the current water level. Each of these scenarios can happen:
We reached a column that is higher than the water level;
We reached a column that is lower than the water level;
We reached a column that has the same height as the water level;
The first one defines a new water level. For the two others, notice that to count the blocks, all we need to do is add water_level - height to the current total.
This will only cause a problem once we reach the end. Consider this input, for instance:
{2, 0, 0, 3, 0, 0}
Notice that the water level on the two last items should be 0, but we have just set it to 3! To fix this, we simply discard the result of the last iteration (from 3 to the end) and do a reverse iteration from the end to that point.
If this all sounds a bit tricky, you will see that the implementation is actually quite simple. Following is what I came up with: It uses some recursion to simplify things, and works on any pair of iterators:
#include <iterator> // std::reverse_iterator
template<typename It>
int pass(It begin, It end) {
if (end - begin <= 1) return 0;
int result = 0;
auto it = begin;
while(++it != end) {
// We keep track of the current water level by simply querying the begin iterator.
if (*it <= *begin) {
result += *begin - *it;
} else {
// We need to define a new water level. Let's just do a new pass, with the begin pointing to the new column.
return result + pass(it, end);
}
}
// If we got here, it means we reached the end. We should discard the result, and do a reverse pass instead
return pass(std::reverse_iterator(end), std::reverse_iterator(begin));
}
Use it like this:
int main() {
std::vector<int> v{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1};
std::cout << pass(v.begin(), v.end());
}
// Output: 6

Stuck in the following dp code

I wrote the following dp code for finding the prime factors of a number.
#include <bits/stdc++.h>
#define max 1000001
using namespace std;
vector <int> prime;
vector<bool> isprime(max,true);
vector<bool> visited(max,false);
vector<int> data(max,-1);
void dp(int n,int last)
{
if(n >= max || visited[n])
return;
visited[n] = true;
for(int i = last;i<prime.size();i++)
{
if(n*prime[i] >= max || data[n*prime[i]] != -1)
return;
data[n*prime[i]] = prime[i];
dp(n*prime[i],i);
}
}
int main()
{
isprime[1] = false;
data[1] = 1;
for(int i = 4;i<max;i += 2)
isprime[i] = false;
for(int i = 3; i*i< max;i += 2)
{
for(int j = i*i; j < max;j += i)
isprime[j] = false;
}
prime.push_back(2);
data[2] = 2;
for(int i =3;i<max;i += 2)
if(isprime[i])
{
prime.push_back(i);
data[i] = i;
}
for(int i = 0;i<prime.size();i++)
{
dp(prime[i],i);
}
cout<<"...1\n";
for(int i = 2;i<=8000;i++)
{
cout<<i<<" :- ";
int temp = i;
while(temp!= 1)
{
cout<<data[temp]<<" ";
temp = temp/data[temp];
}
cout<<endl;
}
return 0;
}
Here, last is the last index of prime number n.
But I am getting segmentation fault for this, when I change max to 10001, it runs perfectly. I'm not getting why is this happening since the data-structures used are 1-d vectors which can hold values up to 10^6 easily.
I checked your program out using GDB. The segfault is taking place at this line:
if(n*prime[i] >= max || data[n*prime[i]] != -1)
In your first ever call to DP in your for loop, where you call dp(2,0), the recursive calls eventually generate this call: dp(92692,2585).
92692 * 2585 = 239608820
This number is larger than a 32 bit integer can hold, so the r-value generated by the integer multiplication of those two numbers overflows and becomes negative. nprime[i] becomes negative, so your first condition of the above loop fails, and the second is checked. data[n * prime[i]] is accessed, and since n*prime[i] is negative, your program accesses invalid memory and segfaults. To fix this, simply change n to a long long in your parameter list and you should be fine.
void dp(long long n, int last)

Finding Longest Increasing Sub Sequence in a round table of numbers

I was recently working on the following problem.
http://www.codechef.com/problems/D2
The Chef is planning a buffet for the DirectiPlex inauguration party, and everyone is invited. On their way in, each guest picks up a sheet of paper containing a random number (this number may be repeated). The guests then sit down on a round table with their friends.
The Chef now decides that he would like to play a game. He asks you to pick a random person from your table and have them read their number out loud. Then, moving clockwise around the table, each person will read out their number. The goal is to find that set of numbers which forms an increasing subsequence. All people owning these numbers will be eligible for a lucky draw! One of the software developers is very excited about this prospect, and wants to maximize the number of people who are eligible for the lucky draw. So, he decides to write a program that decides who should read their number first so as to maximize the number of people that are eligible for the lucky draw. Can you beat him to it?
Input
The first line contains t, the number of test cases (about 15). Then t test cases follow. Each test case consists of two lines:
The first line contains a number N, the number of guests invited to the party.
The second line contains N numbers a1, a2, ..., an separated by spaces, which are the numbers written on the sheets of paper in clockwise order.
Output
For each test case, print a line containing a single number which is the maximum number of guests that can be eligible for participating the the lucky draw.
Constraints
1 ≤ N ≤ 10000
You may assume that each number number on the sheet of paper; ai is randomly generated, i.e. can be with equal probability any number from an interval [0,U], where U is some upper bound (1 ≤ U ≤ 106).
Example
Input:
3
2
0 0
3
3 2 1
6
4 8 6 1 5 2
Output:
1
2
4
On checking the solutions I found this code:
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
#define LIMIT 37
using namespace std;
struct node {
int val;
int index;
};
int N;
int binary(int number, vector<int>& ans) {
int start = 0;
int n = ans.size();
int end = n - 1;
int mid;
if (start == end)
return 0;
while (start != end) {
mid = (start + end) / 2;
if (ans[mid] == number)
break;
if (ans[mid] > number)
end = mid;
else
start = mid + 1;
}
mid = (start + end) / 2;
return mid;
}
void display(vector<int>& list) {
cout << endl;
for (int i = 0; i < list.size(); i++)
cout << list[i] << " ";
cout << endl;
}
int maxsubsequence(vector<int>& list) {
vector<int> ans;
int N = list.size();
ans.push_back(list[0]);
int i;
// display(list);
for (i = 1; i < N; i++) {
int index = binary(list[i], ans);
/*if(index+1<ans.size())
continue;*/
if (list[i] < ans[index])
ans[index] = list[i];
if (list[i] > ans[index])
ans.push_back(list[i]);
// display(ans);
}
return ans.size();
}
int compute(int index, int* g) {
vector<int> list;
list.push_back(g[index]);
int itr = (index + 1) % N;
while (itr != index) {
list.push_back(g[itr]);
itr = (itr + 1) % N;
}
return maxsubsequence(list);
}
int solve(int* g, vector<node> list) {
int i;
int ret = 1;
for (i = 0; i < min(LIMIT, (int)list.size()); i++) {
// cout<<list[i].index<<endl;
ret = max(ret, compute(list[i].index, g));
}
return ret;
}
bool cmp(const node& o1, const node& o2)
{ return (o1.val < o2.val); }
int g[10001];
int main() {
int t;
cin >> t;
while (t--) {
cin >> N;
vector<node> list;
int i;
for (i = 0; i < N; i++) {
node temp;
cin >> g[i];
temp.val = g[i];
temp.index = i;
list.push_back(temp);
}
sort(list.begin(), list.end(), cmp);
cout << solve(g, list) << endl;
}
return 0;
}
Can someone explain this to me. I am well aware of calculating LIS in nlog(n).
What I am not able to understand is this part:
int ret = 1;
for (i = 0; i < min(LIMIT, (int)list.size()); i++) {
// cout<<list[i].index<<endl;
ret = max(ret, compute(list[i].index, g));
}
and the reason behind sorting
sort(list.begin(),list.end(),cmp);
This algorithm is simply guessing at the starting point and computing the LIS for each of these guesses.
The first value in a LIS is likely to be a small number, so this algorithm simply tries the LIMIT smallest values as potential starting points.
The sort function is used to identify the smallest values.
The for loop is used to check each starting point in turn.
WARNING
Note that this algorithm may fail for certain inputs. For example, consider the sequence
0,1,2,..,49,9900,9901,...,99999,50,51,52,...,9899
The algorithm will try just the first 37 starting points and miss the best starting point at 50.
You can test this by changing the code to:
int main() {
int t;
t=1;
while (t--) {
N=10000;
vector<node> list;
int i;
for (i = 0; i < N; i++) {
node temp;
if (i<50)
g[i]=i;
else if (i<150)
g[i]=9999-150+i;
else
g[i]=i-100;
temp.val = g[i];
temp.index = i;
list.push_back(temp);
}
sort(list.begin(), list.end(), cmp);
cout << solve(g, list) << endl;
}
return 0;
}
This will generate different answers depending on whether LIMIT is 37 or 370.
In practice, for randomly generated sequences it will have a good chance of working (although I don't know how to compute the probability exactly).