Dijkstra algorithm without diagonal moves - c++

Sorry if this question is a bit stupid, but I can't find a proper solution. I want to get the shortest way from a point to another. I have found a code in internet, but this code give me the path with diagonals and I need it only with vertical and horizontal movements. Anyone could tell me what should I change? Because I've tried several modifications and none of them seem to work. This is the code:
Thanks in advance.
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
class Cell
{
int x;
int y;
public:
int getx(){
return x;
}
int gety(){
return y;
}
void setx(int x){
this->x = x;
}
void sety(int y){
this->y = y;
}
bool operator==(Cell o) {
return x==o.x && y==o.y;
}
Cell operator=(Cell o) {
x = o.x;
y = o.y;
return *this;
}
Cell(int x, int y):x(x),y(y){ }
Cell():x(0),y(0){}
};
vector<Cell> getShortestPath(Cell ori, Cell dest, int array[], int width, int height);
int main()
{
int ejemplo[] = {
0,1,0,1,0,0,0,0, //0: void
0,1,0,1,0,0,0,0, //1: obstacle
0,1,0,1,0,0,0,0,
0,1,0,1,0,0,0,0,
0,1,0,1,0,0,0,0,
0,1,0,1,0,0,0,0,
0,0,0,1,0,0,0,0,
0,0,0,0,0,0,0,0};
vector<Cell> camino= getShortestPath(Cell(2,0),Cell(0,7),ejemplo,8,8);
for(int i = 0; i < camino.size(); i++) {
cout << "(" << camino[i].getx() << ", " << camino[i].gety() << ")" << endl;
}
}
vector<Cell> getShortestPath(Cell ori, Cell dest, int array[], int width, int height)
{
if ( ori == dest )
return vector<Cell>();
unsigned int *sizes = new unsigned int[width*height];
Cell *prev = new Cell[width*height];
for(int i = 0; i < width*height; i++) {
sizes[i] = -1;
prev[i] = Cell(-1,-1);
}
sizes[ori.getx()+ori.gety()*width] = 0;
prev[ori.getx()+ori.gety()*width] = ori;
queue<Cell> porVisitar;
porVisitar.push(ori);
while(!porVisitar.empty())
{
Cell cur = porVisitar.front();
porVisitar.pop();
cout << porVisitar.size() << endl;
for(int i = -1; i < 2; i++)
for(int j = -1; j < 2; j++)
if((cur.getx()+j)>=0 && (cur.getx()+j)<width && (cur.gety()+i)>=0 && (cur.gety()+i)<height && //is not out of bounds
array[(cur.getx()+j)+(cur.gety()+i)*width]==0 && //is not an obstable
sizes[cur.getx()+cur.gety()*width]+1 < sizes[(cur.getx()+j)+(cur.gety()+i)*width] //there is not a better path
) {
sizes[(cur.getx()+j)+(cur.gety()+i)*width]=sizes[cur.getx()+cur.gety()*width]+1;
prev[(cur.getx()+j)+(cur.gety()+i)*width]=Cell(cur.getx(),cur.gety());
porVisitar.push(Cell(cur.getx()+j,cur.gety()+i));
}
}
if(prev[dest.getx()+dest.gety()*width]==Cell(-1,-1))
return vector<Cell>();
Cell pp = dest;
vector<Cell> res(sizes[dest.getx()+dest.gety()*width]+1);
for(int i = res.size()-1; !(pp == ori); i-- )
{
res[i] = pp;
pp = prev[pp.getx()+pp.gety()*width];
}
return res;

Consider the subgraph:
a b c
d N e
f g h
where N is your current node/vertex. When adding neighbors to your potential path list (or queue, or whatever), only add b, d, e, and g. The above code adds a-h.
Hint: this happens in the nested for loop.
Answer: The conditional should read if((i != -1 && i != 1) || (j != 1 && j != -1)).

Related

Bellman Ford parsing Source & Destination as a Character rather than an Integer

I am working on a data structures assignment which requires me to read from a file which contains a source, destination & weight (e.g t,x,5) and I've used online resources such a geeksforgeeks from where I have altered my code to make it work. Although what I am currently doing is kind of a hack/workaround which reads the character and converts it to an integer which basically defeats the purpose.
I want to parse the characters as is and not convert it to an integer.
Reference: https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/
So basically what I doing is that i am treating {s,t,x,y,z} as {0,1,2,3,4} which basically works
if(a[0]=='s')
{
graph->edge[index].src = 0;
}
and so on...
File that's being read
t,x,5
t,y,8
t,z,-4
x,t,-2
y,x,-3
y,z,9
z,x,7
z,s,2
s,t,6
s,y,7
And here is the working code for it
#include<bits/stdc++.h>
#include<fstream>
#include<string>
using namespace std;
struct Edge {
int s, d, w;
};
struct Graph {
int V, E;
struct Edge* edge;
};
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = new Graph;
graph->V = V;
graph->E = E;
graph->edge = new Edge[E];
return graph;
}
void initialize_single_source(int distance[],int V, int s)
{
for (int i = 0; i < V; i++)
{
distance[i] = INT_MAX;
}
distance[s] = 0;
}
void relax(int distance[], int u, int v, int w)
{
if (distance[v] > distance[u] + w && distance[u] != INT_MAX)
{
distance[v] = distance[u] + w;
}
}
void display(int distance[], int n)
{
char vertex[] = {'s','t','x','y','z'};
cout << "Vertex Distance from Source\n";
for (int i = 0; i < n; ++i)
cout << vertex[i] << "\t\t" << distance[i] << "\n";
}
bool bellman_ford(struct Graph* graph, int s)
{
int V = graph->V;
int E = graph->E;
int distance[V];
initialize_single_source(distance,V,s);
for (int i = 1; i <= V - 1; i++)
{
for (int j = 0; j < E; j++)
{
int u = graph->edge[j].s;
int v = graph->edge[j].d;
int w = graph->edge[j].w;
relax(distance,u,v,w);
}
}
for (int i = 0; i < E; i++) {
int u = graph->edge[i].s;
int v = graph->edge[i].d;
int w = graph->edge[i].w;
if (distance[v] > distance[u] + w && distance[u] != INT_MAX)
return false;
}
display(distance, V);
return true;
}
int main()
{
int V = 5;
int E = 10;
struct Graph* graph = createGraph(V, E);
int index = 0;
string a;
ifstream infile("adjlist.txt");
while(getline(infile,a))
{
if(a[0]=='s')
{
graph->edge[index].s = 0;
}
else if(a[0]=='t')
{
graph->edge[index].s = 1;
}
else if(a[0]=='x')
{
graph->edge[index].s = 2;
}
else if(a[0]=='y')
{
graph->edge[index].s = 3;
}
else if(a[0]=='z')
{
graph->edge[index].s = 4;
}
if(a[2]=='s')
{
graph->edge[index].d = 0;
}
else if(a[2]=='t')
{
graph->edge[index].d = 1;
}
else if(a[2]=='x')
{
graph->edge[index].d = 2;
}
else if(a[2]=='y')
{
graph->edge[index].d = 3;
}
else if(a[2]=='z')
{
graph->edge[index].d = 4;
}
if(a[4]!='-')
{
graph->edge[index].w = a[4]-'0';
}
else
{
graph->edge[index].w = -(a[5]-'0');
}
index++;
}
bellman_ford(graph, 0);
return 0;
}
Output:
Vertex Distance from Source
s 0
t 2
x 4
y 7
z -2
One possible solution would be to rewrite Edge as follows
struct Edge {
char s, d;
int w;
};
and use std::map<char, vector<char> > for representing the adjacency lists. Note that this will require you to somehow keep track of the weights and change the remaining parts of the code accordingly.
On a side note, as mentioned by #user4581301, including bits/stdc++ is bad practice. See this for more details.
Converting vertex labels from strings or some other sparse type to densely packed integers is actually pretty common when implementing graph algorithms and can be quite useful.
We do this so that we can use arrays or vectors to store other things corresponding to the vertexes, instead of more complex structures like maps.
The label mapping should be constructed dynamically, though, depending on what labels you actually have instead of hard-coding it. You can use a std::map<char,int> to do it like this:
int getVertexNumber(char c) {
auto it = label_map.find(c);
int num;
if (it != label_map.end()) {
// already had a mapping for this label
num = it->second;
} else {
// new label, starting at 0
num = (int)label_map.size();
label_map[c] = num;
}
return num;
}

Segmentation Fault when dealing with 2D Arrays [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm am trying to dynamically make 2d arrays that are then supposed to be iterated through to check their contents. Whenever I try to use a function that indexes the array I get a segmentation fault. The two functions that are creating the problems are the printg() and get() functions. I'm not sure exactly what I'm doing wrong, but neither of them will work properly for me.
Any help would be great. Thank you.
#ifndef _GRID_H
#define _GRID_H
#include <iostream>
using namespace std;
class Grid
{
public:
Grid();
Grid(const Grid& g2);
Grid(int x, int y, double density);
Grid(string file);
~Grid();
bool check(int x, int y); //check if a cell is inhabited or not
bool isEmpty();//check if a grid is living
bool equals(const Grid& g2);//checks if two grids are equal
void kill(int x, int y);//kill a cell
void grow(int x, int y);//grow a cell
int getSize();
int getNumRows();
int getNumCol();
int getNumLiving();
void printg(int r, int c);
char get(int x, int y) const;
private:
int size; //number of cells in grid
int row; //row length (number of columns)
int column; //column length (number of rows)
int num_living; //number of X's in the grid
char** myGrid;
};
#endif
#include "Grid.h"
#ifndef _GRID_C
#define _GRID_C
#include <iostream>
#include <cmath>
#include <fstream>
#include <cstdlib>
//compile with g++ -I /home/cpsc350/GameOfLife Grid.cpp
using namespace std;
Grid::Grid() //do i need a default constructor????
{
char myGrid[10][10] = {{0,1,2,3}, {4,5,6,7}, {8,9,10,11}};
row = 10;
column = 10;
size = 100;
}
Grid::Grid(const Grid& g2)//copy constructor/////////////help
{
size = g2.size;
row = g2.row;
column = g2.column;
num_living = g2.num_living;
char** myGrid = new char*[row];
for(int i = 0; i < row; i++)
myGrid[i] = new char[column];
for(int i1 = 0; i1 < row; i1++)
{
for(int i2 = 0; i2 < column; i2++)
{
//copy(&g2[i1][i2], &g2[i1][i2]+row*column,&myGrid[i1][i2]);
myGrid[i1][i2] = g2.get(i1,i2);
}
}
}
Grid::Grid(int x, int y, double density)
{
char** myGrid = new char*[x];
for(int i = 0; i < x; i++)
myGrid[i] = new char[y];
row = x;
column = y;
size = x*y;
num_living = size * density;
string str = "";
for(int a = 0; a < num_living; a++)//adds the density of X's to a string
{
str += 'X';
}
for(int a = 0; a < size - num_living; a++)//adds the rest to the string
{
str += '-';
}
int randnum;
//randomly generates indicies in the string str and puts them into the array
for(int i1 = 0; i1 < column; i1++)
{
for(int i2 = 0; i2 < row; i2++)
{
//generate random numbers from index 0 to length of string - 1
if(str.length()>1)
{
randnum = (rand()%(str.length()-1))+1;
}
else
{
randnum = 0;
}
myGrid[i1][i2] = str[randnum];
str.erase(randnum);
}
}
}
Grid::Grid(string file)
{
num_living = 0;
//code to create a 2d array from a filepath
ifstream openfile(file);
//error handling
if(! openfile)
{
cout << "Error, file could not be opened" << endl;
exit(0);
}
openfile >> column;//gets number of rows
openfile >> row;//gets number of columns
size = row*column;
char** myGrid = new char*[row];
for(int i = 0; i < row; i++)
myGrid[i] = new char[column];
for(int x = 0; x<column; x++)
{
for(int y = 0; y<row; y++)
{
openfile >> myGrid[x][y];
if(! openfile)//error handling
{
cout << "Error reading file at " << row << "," << column << endl;
}
if(myGrid[x][y] == 'X')
{
num_living++;
}
}
}
openfile.close();
}
Grid::~Grid()
{
if(myGrid)
{
for(int i = 0; i < row; i++)
{
delete []myGrid[i];
}
delete []myGrid;
}
}
void Grid::kill(int x, int y)
{
if(myGrid[x][y] == 'X')
{
num_living--;
}
myGrid[x][y] = '-';
}
void Grid::grow(int x, int y)
{
if(myGrid[x][y] == '-')
{
num_living++;
}
myGrid[x][y] = 'X';
}
bool Grid::check(int x, int y)
{
if(y<0 || x<0)
{
return(false);
}
return (myGrid[x][y] == 'X');
}
bool Grid::isEmpty()
{
return (num_living == 0);
}
bool Grid::equals(const Grid& g2)
{
if(size != g2.size) //checks if sizes are equal
{
return false;
}
if(row != g2.row)//checks if numRows are equal
{
return false;
}
if(column != g2.column)//checks if numCol are equal
{
return false;
}
if(num_living != g2.num_living)//checks if numliving are equal
{
return false;
}
for(int x = 0; x < row; x++)//checks each element
{
for(int y = 0; y < column; y++)
{
if(myGrid[x][y] != g2.get(x,y))
{
return false;
}
}
}
return true;
}
int Grid::getSize()
{
return(size);
}
int Grid::getNumRows()
{
return(column);
}
int Grid::getNumCol()
{
return(row);
}
int Grid::getNumLiving()
{
return(num_living);
}
void Grid::printg(int r, int c)
{
for(int x = 0; x < r; x++)
{
for(int y = 0; y < c; y++)
{
cout << myGrid[x][y];
}
cout << endl;
}
}
char Grid::get(int x, int y) const
{
return myGrid[x][y];
}
#endif
The problem that I see at first is that both your default and copy constructor do not initialize myGrid. what you are doing in them will create an additional array with the same name which 'shadows' myGrid. instead you have to do:
Grid::Grid(const Grid& g2)
{
size = g2.size;
row = g2.row;
column = g2.column;
num_living = g2.num_living;
myGrid = new char*[row]; // removed "char**" at the start of this line
for(int i = 0; i < row; i++)
myGrid[i] = new char[column];
for(int i1 = 0; i1 < row; i1++)
{
for(int i2 = 0; i2 < column; i2++)
{
//copy(&g2[i1][i2], &g2[i1][i2]+row*column,&myGrid[i1][i2]);
myGrid[i1][i2] = g2.get(i1,i2);
}
}
}
your default constructor has the same problem. but note that you can't initialize it with braces. but you don't have to have a default constructor if you are not using it.

Unable to call a public function inside of another public function

(Edit: change suggested in the comments section now allows the desired behavior)
I'm developing an agent-based simulation in C++, and so far I'm able to run 1 simulation and I transcribe the results manually. It consists of an Environment class with a 2-d array with agents (hunters and preys)
To automate the data collection, I'm trying to implement some functions so that I can later transcribe relevant results of each simulation to a CSV file.
The following code in Visual Studio generates the Environment, populates it, counts the agents and display an ASCI map of the hunters and preys with a legend.
#include <iostream>
#include <cstdlib> // for rand
#include <ctime> // for time
#include <vector>
#include <Windows.h> //for color in output
using namespace std;
const int WORLDSIZEX = 100;
const int WORLDSIZEY = 30;
enum AgentType { PREY, HUNTER };
class Environment;
class Agent {
public:
Agent(Environment* aWorld, int xcoord, int ycoord);
virtual ~Agent() { }
virtual AgentType getType() const = 0;
virtual char representation() const = 0;
protected:
int x;
int y;
Environment* world;
private:
};
struct Position {
int x;
int y;
};
class Environment {
public:
Environment(unsigned int seed, int _id, int _initialPopulationPreys, int _initialPopulationHunmters);
~Environment();
Agent* getAt(int x, int y) const;
void setAt(int x, int y, Agent* org);
void display();
Position randomPosition() const;
Position randomPositionHunter() const;
int numberPreys();
int numberHunters();
private:
Agent* grid[WORLDSIZEX][WORLDSIZEY];
void createOrganisms(AgentType orgType, int count);
int id;
int timeStep;
int initialPopulationPreys;
int initialPopulationHunters;
};
class Hunter : public Agent {
public:
Hunter(Environment* aWorld, int xcoord, int ycoord);
AgentType getType() const;
char representation() const;
private:
bool altruistic;
};
class Prey : public Agent {
public:
Prey(Environment* aWorld, int xcoord, int ycoord);
AgentType getType() const;
char representation() const;
private:
int huntingDifficulty;
};
Prey::Prey(Environment* aWorld, int xcoord, int ycoord) : Agent(aWorld, xcoord, ycoord) { huntingDifficulty = int(rand() % 3); }
AgentType Prey::getType() const { return PREY; }
char Prey::representation() const { return 'o'; }
Hunter::Hunter(Environment* aWorld, int xcoord, int ycoord) : Agent(aWorld, xcoord, ycoord) { }
AgentType Hunter::getType() const { return HUNTER; }
char Hunter::representation()const { return 'X'; }
Agent::Agent(Environment* aWorld, int xcoord, int ycoord) {
world = aWorld;
x = xcoord;
y = ycoord;
world->setAt(x, y, this);
}
Environment::Environment(unsigned int seed, int _id, int _initialPopulationPreys, int _initialPopulationHunters) {
srand(seed);
id = _id;
initialPopulationPreys = _initialPopulationPreys;
initialPopulationHunters = _initialPopulationHunters;
for (int i = 0; i < WORLDSIZEX; i++) {
for (int j = 0; j < WORLDSIZEY; j++) {
grid[i][j] = NULL;
}
}
timeStep = 0;
createOrganisms(PREY, initialPopulationPreys);
createOrganisms(HUNTER, initialPopulationHunters);
}
Environment::~Environment() {
for (int i = 0; i < WORLDSIZEX; i++) {
for (int j = 0; j < WORLDSIZEY; j++) {
if (grid[i][j] != NULL) {
delete grid[i][j];
}
}
}
}
Agent* Environment::getAt(int x, int y) const {
if ((x >= 0) && (x < WORLDSIZEX) && (y >= 0) && (y < WORLDSIZEY)) {
return grid[x][y];
}
else {
return NULL;
}
}
void Environment::setAt(int x, int y, Agent* org) {
if ((x >= 0) && (x < WORLDSIZEX) && (y >= 0) && (y < WORLDSIZEY)) {
grid[x][y] = org;
}
}
// Displays the world in ASCII.
void Environment::display() {
int numPreys = 0;
int numHunters = 0;
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Remember how things were when we started
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hstdout, &csbi);
cout << endl << endl;
for (int j = 0; j < WORLDSIZEY; j++) {
for (int i = 0; i < WORLDSIZEX; i++) {
if (grid[i][j] == NULL) {
cout << "_";
}
else {
if (grid[i][j]->getType() == PREY) {
SetConsoleTextAttribute(hstdout, 10);
numPreys++;
}
else if (grid[i][j]->getType() == HUNTER) {
SetConsoleTextAttribute(hstdout, 12);
numHunters++;
}
cout << grid[i][j]->representation();
SetConsoleTextAttribute(hstdout, csbi.wAttributes);
}
}
cout << endl;
}
cout << "Preys 'o': " << numPreys << " Hunters 'X': " << numHunters << endl;
cout << "Timestep:" << timeStep << " World ID:" << id << endl;
}
Position Environment::randomPosition() const { // returns a random number in the range 0 to WORLDSIZEX - 1 (or WORLDSIZEY - 1)
Position p;
p.x = rand() % WORLDSIZEX;
p.y = rand() % WORLDSIZEY;
return p;
}
Position Environment::randomPositionHunter() const { // returns a random number in the central fifth of the grid
Position p;
int subGridSizeX = WORLDSIZEX / 5;
int subGridSizeY = WORLDSIZEY / 5;
p.x = subGridSizeX * 1 + (rand() % (3 * subGridSizeX));
p.y = subGridSizeY * 2 + (rand() % subGridSizeY);
return p;
}
int Environment::numberPreys() {
int numPreys = 0;
for (int j = 0; j < WORLDSIZEY; j++) {
for (int i = 0; i < WORLDSIZEX; i++) {
if (grid[i][j] && grid[i][j]->getType() == PREY) {
numPreys++;
}
}
}
return numPreys;
}
int Environment::numberHunters() {
int numHunters = 0;
for (int j = 0; j < WORLDSIZEY; j++) {
for (int i = 0; i < WORLDSIZEX; i++) {
if (grid[i][j] && grid[i][j]->getType() == HUNTER) {
numHunters++;
}
}
}
return numHunters;
}
void Environment::createOrganisms(AgentType orgType, int count) {
int orgCount = 0;
while (orgCount < count) {
Position p = randomPosition();
Position q = randomPositionHunter();
if (orgType == PREY) {
if (grid[p.x][p.y] == NULL) { // Only put Organism in empty spot
orgCount++;
new Prey(this, p.x, p.y); // Create a Prey and put it into the world
}
}
else if (orgType == HUNTER) {
if (grid[q.x][q.y] == NULL) { // Only put Organism in empty spot
orgCount++;
new Hunter(this, q.x, q.y); // Create a Hunter and put it into the world
}
}
}
}
int main() {
int initialPreys = 60;
int initialHunters = 15;
int id = 0;
//Creating the environment
int seed = time(0);
Environment myWorld(seed, id, initialPreys, initialHunters);
cout << "This is the setup of the environment for all the simulations" << endl;
myWorld.display();
char ch;
return 0;
}
I would like to replace the Environment::display() function with:
void Environment::display() {
int numPreys = numberPreys();
int numHunters = numberHunters();
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Remember how things were when we started
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hstdout, &csbi);
cout << endl << endl;
for (int j = 0; j < WORLDSIZEY; j++) {
for (int i = 0; i < WORLDSIZEX; i++) {
if (grid[i][j] == NULL) {
cout << "_";
}
else {
if (grid[i][j]->getType() == PREY) {
SetConsoleTextAttribute(hstdout, 10);
}
else if (grid[i][j]->getType() == HUNTER) {
SetConsoleTextAttribute(hstdout, 12);
}
cout << grid[i][j]->representation();
SetConsoleTextAttribute(hstdout, csbi.wAttributes);
}
}
cout << endl;
}
cout << "Preys 'o': " << numPreys << " Hunters 'X': " << numHunters << endl;
cout << "Timestep:" << timeStep << " World ID:" << id << endl;
}
But then, the function doesn't display anything and the console window closes after a while.
My question: How can I call the counting functions inside of the display function?

Negamax algorithm

I have worked quite a bit with my tictactoe, but never got it working. Here is what I have so far:
static int evaluate(board b)
{
if (is_win curr_move_noughts)
{
return 1;
}
else if (is_win crosses)
{
return -1;
}
else
{
return 0;
}
}
int evaluateNegamax(board b)
{
if (curr_move_noughts) // Max player
return evaluate(b);
else
return -evaluate(b);
}
tuple<int, move> Search(int depth, board b)
{
board combined(); =b;
int w = 0;
w = Evaluate(b);
int move;
int bestScore = std::numeric_limits<int>::min();
bool bestMove = false;
if(depth == 0) return w;
int x=0, int y=0;
for (int x = 0; x < 9; ++x) {
for (int y = 0; y < 9; ++y) {
while (!occupied(x,y));
make_move(x, y);
score = -Search(depth-1,b); // recursion
unMake(b);
if(score > bestScore) {
bestScore = score;
bestMove = move;
}
}
}
// return the best move
return make_tuple(bestScore, bestMove);
}
Well, obviously " move " needs to be linked to XY coordinate but I don`t kow how.
I have defined make_move like this:
void make_move( size_t row, size_t col, board & b )
{
if (free(row, col))
{
b[pos(row, col)] = true;
last_move_row = row ;
last_move_col = col ;
}
}

Querying for a value that's bigger than X, while having another condition

I have list of pair [x;y] where x is unique and y can be duplicate(integers).
Here lies a problem:
Given a pair [x;y], find new pair [k;m], such that:
k > x
m >= y
k - x is minimized.
Now, I've solved this problem with this logic; I sort pairs by x, and then start naive O(n^2) algorithm on it. It seems to work fine, except it's too slow.
Can I do better?
The actual problem im trying to solve, is here: http://www.spoj.com/problems/VBOSS/
and my current code:
#include <stdio.h>
#include <utility>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
struct employee
{
int id;
int salary;
int height;
int parent_index;
int sub_ordinates;
int cur;
bool important;
bool operator < (const employee& e) const
{
if(height == e.height)
return salary > e.salary;
return (height > e.height);
}
};
// problem states explictly that no two employees
// have same salary.
struct salary_predicate
{
inline bool operator() (const employee& struct1, const employee& struct2)
{
return (struct1.salary > struct2.salary);
}
};
const int MAX_EMPLOYEES = 30000;
const int MAX_QUERIES = 200;
employee employees[MAX_EMPLOYEES];
int queries[MAX_QUERIES];
int main()
{
int test_cases;
scanf("%d", &test_cases);
while(test_cases--)
{
int employeeCount, queryCount;
scanf("%d %d", &employeeCount, &queryCount);
int i = 0;
int j = 0;
while(i < employeeCount)
{
employees[i].parent_index = -1;
employees[i].sub_ordinates = 0;
employees[i].cur = i;
employees[i].important = false;
scanf("%d %d %d", &employees[i].id, &employees[i].salary, &employees[i].height);
i++;
}
map<int, int> mapper;
while(j < queryCount)
{
scanf("%d", &queries[j]);
mapper.insert(pair<int, int>(queries[j], -1));
j++;
}
// now step1; sort employees structure
// based on SALARY!!
sort(employees, employees + employeeCount, salary_predicate());
for(int k = 0; k < employeeCount; k++)
{
employees[k].cur = k;
if(mapper.find(employees[k].id) != mapper.end())
{
mapper[employees[k].id] = k;
employees[k].important = true;
}
}
int found = 0;
for(int l = employeeCount - 1; l >= 0; l--)
{
int gef = l - 1;
// check out information about previous worker,
// he might give us some valuable information!
// with his help, we know if we can skip some shit :)
if(l + 1 < employeeCount && employees[l + 1].parent_index != -1)
{
// if previous employee is smaller than our current employee
// then we can skip some people, becase we know that answer cant be
// smalle than that :)
if(employees[l + 1].height <= employees[l].height)
gef = employees[l + 1].parent_index - 1;
}
// find boss!
for(int b = gef; b >= 0; b--)
{
if(employees[b].height >= employees[l].height)
{
employees[l].parent_index = b;
employees[b].sub_ordinates += employees[l].sub_ordinates + 1;
break;
}
}
// this bit makes sure if we have processed all necessay things,
// then we can basically stop our work.
if(employees[l].important) found++;
if(found == mapper.size()) break;
}
// time to print it out.
for(int b = 0; b < queryCount; b++)
{
int id = queries[b];
int index = mapper[id];
int parent_index = employees[index].parent_index;
int parent = parent_index < 0 ? 0 : employees[parent_index].id;
printf("%d %d\r\n", parent, employees[index].sub_ordinates);
}
}
return 0;
}
salary=x, and height=y.
I would start by eliminating all records where m<y or k<=x. Then find the item with the smallest k value out of what's left. Both of these should be linear, so your overall complexity should also be linear.
struct p {
int k, m;
};
p find_item(p xy, std::vector<p> &values) {
auto end = std::partition(values.begin(), values.end(),
[xy](p const &v) { return xy.k < v.k || xy.m >= v.m; });
return *std::min_element(values.begin(), end,
[](p const &a, p const &b) { return a.k < b.k; });
}