某R开头公司在Hackerrank上的一道3小时面试题

题目:

在世界的某个地方(具体记不清了,好像是北极附近)有一些岛(Vertices)和岛之间的桥(Edges)。因为气温太低,有些桥比较人性化,桥面安装了加热设备(HOT BRIDGES),但为了省钱(或是其他原因,记不清了)不是所有桥都装有加热设备 (COLD BRIDGES)。假设一个人从某个岛(Source)通过一些桥去往另一个岛(Destination),求满足以下条件的最短路径(Djistra)是否存在:

1. 该人必须交替使用COLD和HOT的桥,即如果上一个走到桥是HOT,下一个走的必须是COLD,vice versa (理由是连续走两个COLD会冻死,连续走两个HOT会热死)。

2. 两个岛之间可能会有两座桥,一座HOT,一座COLD。

3. 桥是单向的(有向边)。

程序有如下一些约束条件:

1. 输入是STDIN,输出是STDOUT。

2. 桥的个数和岛的格式在Int表示范围内

3. 输入格式如下:

2

2 1 0 1

0 1 HOT

2 1 0 1

0 1 COLD

其中第一行的“2”表示程序有两个测试用例。 接下来的 2 1 0 1 表示2个顶点,1条边,起点为0号顶点,终点为1号顶点。接下来的 0 1 HOT为边的描述:从0到1的一条HOT边。接下来的2 1 0 1是第二个测试用例,定义如上。


思路:变种Dijkstra算法,需要为每个岛(顶点)保存两个distances,一个为通过HOT到达此岛的distance,一个为通过COLD到达的distance。同样的,也需要两个排序set来对COLD和HOT排序。

题解:

#include <iostream>
#include <map>
#include <list>
#include <set>
#include <limits>
#include <string>

using namespace std;

typedef int vertex_t;
typedef bool status_t;

struct edge {
    vertex_t target;
    status_t status;
    edge(vertex_t v, status_t s):target(v),status(s){}
};

template <typename T1, typename T2>  
struct comparator   
{  
    bool operator()( pair<T1, T2> p1, pair<T1, T2> p2)  
    {  
        return p1.first < p2.first;  
    }  
}; //The comparator used for sorting the edge weights.

typedef map<vertex_t, list<edge>> adjacentList;
// Store the minimum distances from source to each intermediate nodes and the destination.
typedef map<vertex_t, int> minDistance;
typedef set<pair<int, vertex_t>, comparator<int, vertex_t>> sortedEdges;

void buildGraph(map<vertex_t, list<edge>> & graph, int & s, int & e, int & nodes) {
    int numOfNodes, numOfEdges, start, end;
    cin >> numOfNodes >> numOfEdges >> start >> end;
	nodes = numOfNodes;
    s = start; e = end;
    for( int i = 0; i < numOfEdges; i++) {
        vertex_t first, second;
        status_t status;
		char temp[10];
        cin >> first >> second >> temp;
		if(temp == "COLD")
			status = false;
		else if(temp == "HOT")
			status = true;
        graph[first].push_back(edge(second, status));
    }
}

void shortestPath(vertex_t source, adjacentList & graph, minDistance & distancesHot, minDistance & distancesCold) {
   
    sortedEdges edgeSetHot, edgeSetCold;
    for(map<vertex_t, list<edge>>::iterator iter =  graph.begin(); iter != graph.end(); iter++) {
        pair<int, vertex_t> wrapper(distancesHot[iter->first], iter->first);
        edgeSetHot.insert(wrapper);
    }

    for(map<vertex_t, list<edge>>::iterator iter =  graph.begin(); iter != graph.end(); iter++) {
        pair<int, vertex_t> wrapper(distancesCold[iter->first], iter->first);
        edgeSetCold.insert(wrapper);
    }
   
    while(!edgeSetHot.empty() && !edgeSetCold.empty()) {
        vertex_t current;

		if(edgeSetHot.begin()->first < edgeSetCold.begin()->first) {
			current = edgeSetHot.begin()->second;
			edgeSetHot.erase(edgeSetHot.begin());
		} else {
			current = edgeSetCold.begin()->second;
			edgeSetCold.erase(edgeSetCold.begin());
		}

		for(list<edge>::iterator iter =  graph[current].begin(); iter != graph[current].end(); iter++) {
            vertex_t neighbor = iter->target;

            int distanceThroughCurrent;
            if(iter->status) {//Hot
                distanceThroughCurrent = distancesCold[current] + 1;
                if(distanceThroughCurrent < distancesHot[neighbor]) {
                    pair<int, vertex_t> wrapper(distancesHot[neighbor], neighbor);
                    edgeSetCold.erase(wrapper);
                    distancesHot[neighbor] = distanceThroughCurrent;
                    wrapper.first = distancesHot[neighbor];
                    edgeSetHot.insert(wrapper);
                }
            } else {
                distanceThroughCurrent = distancesHot[current] + 1;
                if(distanceThroughCurrent < distancesCold[neighbor]) {
                    pair<int, vertex_t> wrapper(distancesCold[neighbor], neighbor);
                    edgeSetHot.erase(wrapper);
                    distancesCold[neighbor] = distanceThroughCurrent;
                    wrapper.first = distancesCold[neighbor];
                    edgeSetCold.insert(wrapper);
                }               
            }
        }
    }
   
    return;
}

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    int numberOfTestCases = 0;
    cin >> numberOfTestCases;
   
    if(numberOfTestCases) {
        for(int i = 0; i < numberOfTestCases; i++) {
            adjacentList graph;
            int start, end, nodes;
            buildGraph(graph, start, end, nodes);
            
            minDistance distancesHot, distancesCold;

			for(int i = 0; i < nodes; i++) {
				distancesHot[i] = numeric_limits<int>::max();
				distancesCold[i] = numeric_limits<int>::max();
			}
			distancesHot[start] = 0;
			distancesCold[start] = 0;
            shortestPath(start, graph, distancesHot, distancesCold);
           
            int min = numeric_limits<int>::max();
            if(distancesCold[end] < min)
                min = distancesCold[end];
            if(distancesHot[end] < min)
                min = distancesHot[end];
           
            if(min == numeric_limits<int>::max())
                min = -1;
           
            cout << min << endl;
        }
    }
   
    return 0;
}



你可能感兴趣的:(Algorithm,面试题)