标签:+= temp 问题 bsp stream max c++ 多个 存储
问题:假设你是某地区的消防队长,该地区包括N个城市和M条连结城市的公路,N个城市各自驻扎的消防队员数量业已给出,假设你位于城市c1处,当城市c2发生火灾时,你需要从城市c1出发,走最短的路径到达城市c2,与此同时,沿线征兆尽可能多的消防队员。编程解出城市c1与c2之间最短路径的数目,以及最多能征兆多少消防队员。原问题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805523835109376
解决方案:
这是一个典型的求最短路径的问题,直接应用Dijkstra算法就好,在更新节点距离的时候做一点改进,就能直接得到问题的解了。下面简单的回顾一下Dijkstra算法。
Dijkstra算法适用于没有负值权重的图中,将所有节点分为两种集合,一类是未访问集合U,一类是已访问集合V,起始时所有的节点都在未访问集合U中。算法的每一步都是从从未访问集合U中找出一个离初始点最近的节点A,将其置入已访问集合V中,同时需要更新未访问集合U中剩下的节点B(存在多个,这里只说一个)到起始点的距离,此时B到起始点的距离要么不变,要么等于A到起始点的距离加上A到B的距离,谁小就取谁,不可能有第三种情况,也就是说,不可能在集合U中存在一点C,使得B经过C到达起始点的距离小于上述两种情况(这就是为什么Dijkstra算法只适用于没有负值权重的图中,当存在负值权重时,这个C点就可能存在).。
为了满足题目的要求,得到最短路径的数目以及最多能征兆多少消防队员,此时需要在每个节点处都引入一个数组,存储每个节点到达起始点的最短路径数量以及最多可以征兆的消防队员数量,这个数组在初始节点最短路径为1,消防队员数目就是本地的消防队员数目,其他节点都是0。然后在Dijkstra算法更新未访问集合U中剩下的节点B到初始点距离的阶段也同时更新这个数组,具体更新该数组的过程分为两种情况:1.当A到起始点的距离加上A到B的距离小于B到起始点的距离时,B到起始点的距离更新为A到起始点的距离加上A到B的距离,同时更新后的B到起始点的最短路径数目等于A到起始点的最短路径数目,更新后的B到起始点最多可以征兆到的消防队员数目等于A到起始点最多可以征兆到的队员加上B点处驻扎的消防队员数;2.当A到起始点的距离加上A到B的距离等于B到起始点的距离时,B到起始点的距离不需要更新,但是B到起始点的最短路径数目和最多可征兆到的消防队员数目需要更新,更新后的B到起始点的最短路径数目等于更新前的B到起始点的最短路径数目加上A到起始点的最短路径数目(因为这两种路径距离相等),同时更新后的B到起始点最多可以征兆到的消防队员数目取 更新前B到起始点最多可以征兆到的消防队员数目 和 A到起始点最多可以征兆到的消防队员加上B点处驻扎的消防队员数 两者的最大值。
C++代码:
1 #include<iostream> 2 #include<tuple> 3 #include<string.h> 4 #define INFINITY 65536 5 6 using namespace std; 7 8 class Map { 9 private: 10 const int N; //the number of cities 11 const int M; //the number of roads 12 int* rescueTeam; //store the number of rescure teams int each city 13 int* index; //store index that indicates a city is whether included or not 14 int** adjacentArray; //adjacent array 15 int** store; //store the number of shortest path and maximum teams 16 public: 17 Map(int N, int M):N(N),M(M) { //对const类型的变量赋值必须在初始化列表中完成 18 this->rescueTeam = new int[this->N]{ 0 }; 19 this->index = new int[this->N]{ 0 }; 20 this->adjacentArray = new int*[this->N]; //这样赋值,M必须为const?NO, 不用const也可以 21 this->store = new int*[this->N]; 22 for (int i = 0; i < N; i++) { 23 this->adjacentArray[i] = new int[this->N]; 24 this->store[i] = new int[2]{ 0 }; 25 } 26 for (int i = 0; i < N; i++) { 27 for (int j = 0; j < N; j++) { 28 this->adjacentArray[i][j] = INFINITY; //注意memset只能初始化为0或者-1 29 } 30 this->adjacentArray[i][i] = 0; 31 } 32 } 33 int max(int a, int b) { 34 return a > b ? a : b; 35 } 36 int getM() { 37 return this->M; 38 } 39 int getN() { 40 return this->N; 41 } 42 void setIndex(int i) { 43 this->index[i] = 1; 44 } 45 int getIndex(int i) { 46 return this->index[i]; 47 } 48 void setRescureTeam(int position, int number) { 49 this->rescueTeam[position] = number; 50 } 51 int getRescureTeam(int position) { 52 return this->rescueTeam[position]; 53 } 54 void setAdjacent(int array, int column, int value) { 55 this->adjacentArray[array][column] = value; 56 this->adjacentArray[column][array] = value; 57 } 58 int getAdjacent(int array, int column) { 59 return this->adjacentArray[array][column]; 60 } 61 std::tuple<int, int> dijkstra(int c1, int c2); 62 ~Map() { 63 for (int i = 0; i < this->getN(); i++) { 64 delete[] this->adjacentArray[i]; 65 this->adjacentArray[i] = NULL; 66 } 67 } 68 }; 69 70 std::tuple<int, int> Map::dijkstra(int c1, int c2) { 71 this->store[c1][0] = 1; 72 this->store[c1][1] = this->getRescureTeam(c1); 73 int i, j, min, minIndex = 0; 74 for (i = 0; i < this->getN(); i++) { //最多迭代N次 75 min = INFINITY; 76 for (j = 0; j < this->getN(); j++) { //找出未标记的节点集合中离c1最近的 77 if (this->getAdjacent(c1,j) < min && this->getIndex(j) == 0) { 78 min = this->getAdjacent(c1, j); 79 minIndex = j; 80 } 81 } 82 if (minIndex == c2) 83 break; 84 this->setIndex(minIndex); //加上标记,进入标记集合 85 for (j = 0; j < this->getN(); j++) { //更新未标记集合中节点到c1的距离 86 if (this->getIndex(j) || j == minIndex) 87 continue; 88 //第一种情况,此时j到c1的最短路线数与minIndex相同 89 if (this->getAdjacent(c1, j) > this->getAdjacent(c1, minIndex) + this->getAdjacent(minIndex, j)) { 90 this->setAdjacent(c1, j, this->getAdjacent(c1, minIndex) + this->getAdjacent(minIndex, j)); 91 this->store[j][0] = this->store[minIndex][0]; 92 this->store[j][1] = this->store[minIndex][1] + this->getRescureTeam(j); 93 } 94 //第二种情况,此时j到c1的最短路线数等于j到c1的路线加上minIndex的路线 95 else if (this->getAdjacent(c1, j) != INFINITY && this->getAdjacent(c1, j) == this->getAdjacent(c1, minIndex) + this->getAdjacent(minIndex, j)) { 96 this->store[j][0] += this->store[minIndex][0]; 97 this->store[j][1] = this->max(this->store[j][1], this->store[minIndex][1] + this->getRescureTeam(j)); 98 } 99 } 100 } 101 return std::make_tuple(this->store[c2][0], this->store[c2][1]); 102 } 103 104 int main() { 105 int i, temp, tempC1, tempC2, M, N, c1, c2, number, max; 106 cin >> N >> M >> c1 >> c2; 107 Map map(N, M); 108 for (i = 0; i < map.getN(); i++) { 109 cin >> temp; 110 map.setRescureTeam(i, temp); 111 } 112 for (i = 0; i < map.getM(); i++) { 113 cin >> tempC1 >> tempC2 >> temp; 114 map.setAdjacent(tempC1, tempC2, temp); 115 } 116 tie(number, max) = map.dijkstra(c1, c2); 117 cout << number << " " << max; 118 return 0; 119 }
标签:+= temp 问题 bsp stream max c++ 多个 存储
原文地址:https://www.cnblogs.com/TonyMD/p/14644122.html