Cod sursa(job #2452554)

Utilizator ZanoxNonea Victor Zanox Data 31 august 2019 10:58:38
Problema Barbar Scor 60
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 5.19 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <map>

std::ifstream fin("barbar.in");
std::ofstream fout("barbar.out");

int noLines, noColumns;
std::vector<std::vector<char>> dungeonMap;
std::vector<std::pair<int, int>> dragons;
std::pair<int, int> entrance;
std::pair<int, int> exit2;

std::vector<std::vector<int>> dragonDistMap;
std::vector<std::vector<int>> maxPassDistance;

#define x first
#define y second

#define DEBUG 1
#define PRINT(x) if(DEBUG) std::cout<<x<<'\n';

std::string to_string(std::pair<int, int> p) {
    return std::string() + "(" + std::to_string(p.x) + ", " + std::to_string(p.y) + ")";
}

std::string to_string(std::vector<std::pair<int, int>> v) {
    std::string s;
    s.append("[");

    for (int i = 0; i < v.size() - 1; i++)
        s.append(to_string(v[i]) + ", ");

    s.append(to_string(v[v.size() -1]) + "]");

    return s;
}

bool descending(int a, int b) {
    return a > b;
}

void solveTrail();
void populateDragonDistMap();


int main() {
    fin>>noLines>>noColumns;

    dungeonMap.resize(noLines);
    for (std::vector<char>& line : dungeonMap)
        line.resize(noColumns);

    for (int i = 0; i < noLines; i++)
        for (int j = 0; j < noColumns; j++) {
        char spot;
        fin>>spot;

        dungeonMap[i][j] = spot;

        if (spot == 'D')
            dragons.push_back(std::make_pair(i, j));
        else if (spot == 'I')
            entrance = std::make_pair(i, j);
        else if (spot == 'O')
            exit2 = std::make_pair(i, j);
    }

    populateDragonDistMap();

    solveTrail();

    fout<<maxPassDistance[exit2.x][exit2.y];
}

std::vector<std::pair<int, int>> getValidNeighbors(std::pair<int, int> c) {
    std::vector<std::pair<int, int>> sol;

    c.x--;
    if (c.x >= 0) sol.push_back(c);

    c.x+= 2;

    if (c.x < noLines) sol.push_back(c);

    c.x--;
    c.y--;

    if (c.y >= 0) sol.push_back(c);

    c.y+= 2;
    if (c.y < noColumns) sol.push_back(c);

    PRINT("Neighbors detected: " + to_string(sol));

    return sol;
}

std::vector<std::pair<int, int>> getValidOpenNeighbors(std::pair<int, int> c) {
    std::vector<std::pair<int, int>> sol;

    c.x--;
    if (c.x >= 0 && dungeonMap[c.x][c.y] != '*') sol.push_back(c);

    c.x+= 2;
    if (c.x < noLines && dungeonMap[c.x][c.y] != '*') sol.push_back(c);

    c.x--;
    c.y--;
    if (c.y >= 0 && dungeonMap[c.x][c.y] != '*') sol.push_back(c);

    c.y+= 2;
    if (c.y < noColumns && dungeonMap[c.x][c.y] != '*') sol.push_back(c);

    PRINT("Neighbors detected: " + to_string(sol));

    return sol;
}

void solveTrail() {
    PRINT("Entering solve trail");


    //init maxPassDistance
    maxPassDistance.resize(noLines);
    for (std::vector<int>& line : maxPassDistance)
        line.resize(noColumns, -1);

    //insert first elem
    std::multimap<int, std::pair<int, int>, bool(*) (int, int)> expandQueue(descending);
    maxPassDistance[entrance.x][entrance.y] = dragonDistMap[entrance.x][entrance.y];
    expandQueue.insert(std::make_pair(dragonDistMap[entrance.x][entrance.y], entrance));

    bool foundExit = false;

    while (!expandQueue.empty() && !foundExit) {
         std::multimap<int, std::pair<int, int>>::iterator it = expandQueue.begin();
         std::pair<int, int> currentSpot = it->second;
         int currentDist = it->first;

         expandQueue.erase(it);

         PRINT("Exapanding "<<currentSpot.x<<' ' <<currentSpot.y)

         std::vector<std::pair<int, int>> neighbors = getValidOpenNeighbors(currentSpot);

         for (std::pair<int, int> n : neighbors)
         if (maxPassDistance[n.x][n.y] == -1) {
            maxPassDistance[n.x][n.y] = std::min(currentDist, dragonDistMap[n.x][n.y]);
            expandQueue.insert(std::make_pair(maxPassDistance[n.x][n.y], n));

            if (n == exit2) {
                foundExit = true;
                break;
            }
         }
    }
}

void populateDragonDistMap() {
    PRINT("Entering dragon populate map");

    //init dragonDistMap
    dragonDistMap.resize(noLines);
    for (std::vector<int>& line : dragonDistMap)
        line.resize(noColumns, -1);


    //add first elements, the dragons
    std::multimap<int, std::pair<int, int>> expandQueue;
    for (std::pair<int, int> d : dragons) {
        dragonDistMap[d.x][d.y] = 0;

        expandQueue.insert(std::make_pair(0, d));
    }

    while (!expandQueue.empty()) {
         std::multimap<int, std::pair<int, int>>::iterator it = expandQueue.begin();
         std::pair<int, int> currentSpot = it->second;
         int currentDist = it->first;

         expandQueue.erase(it);

         PRINT("Exapanding "<<currentSpot.x<<' ' <<currentSpot.y<<" -> "<<currentDist)

         std::vector<std::pair<int, int>> neighbors = getValidNeighbors(currentSpot);

         for (std::pair<int, int> n : neighbors)
         if (dragonDistMap[n.x][n.y] == -1) {
            PRINT("Adding "<<n.x<<' ' <<n.y<<" -> "<<currentDist + 1<<" to queue")

            dragonDistMap[n.x][n.y] = currentDist + 1;

            expandQueue.insert(std::make_pair(currentDist + 1, n));
         }
    }
}