测试用例:
10 2 2 2 2 10 0 1 1 1 2 1 3 0->1->2 5 10 3 3 3 11 0 10 0 1 1 1 2 1 2 3 1 0 0->1->2->3 6 10 4 4 5 6 7 5 0 0 1 1 0 2 1 1 3 1 2 3 1 3 4 1 3 0->2->3->4 0 10 4 4 4 6 0 11 0 0 1 1 1 2 1 2 3 1 3 4 1 4 0->1->2->3->4 1 10 4 4 8 0 11 3 0 0 1 2 0 2 3 0 3 2 1 2 1 2 3 1 1 4 2 2 4 1 3 4 2 0 0->2->4 1 10 6 6 8 8 9 4 6 7 2 0 1 1 0 2 1 1 3 1 2 3 1 3 4 1 3 5 2 4 6 1 5 6 1 0 0->1->3->4->6 0
- 出发的时候,一边走要一边平衡路上的车数量,也就是,例如先遇到一个需要2个的自行车摊,再遇到一个多出3个的自行车摊,还是需要从出发点携带2个自行车,否则,遇到第一个需要的自行车摊时,无法平衡;后面遇到的这个多出3个的自行车摊,如果没有被消耗掉,那还要带回到自行车中心。后面多出来的这3个,是无法弥补到前面缺乏自行车的地方的。一次路过,路上的自行车数都要平衡
- 可以先保存pre路径,然后再dfs来遍历,达到查找等长,多条件判断路径的目的
#include#include #include #include using namespace std; #define INF 0x3FFFFFFF void dfs(vector * pre, int start, int end, vector * stationBikes, vector * path); struct Path { int end; int length; Path(int end, int length) :end(end), length(length) {} }; void Print(int length, bool* array) { for (int i = 0; i < length; i++) { cout << array[i] << " "; } cout << endl; } int minNeed = INF, minRemain = INF; vector pathSave; void Dijtra(int stationNum, int problemIndex, vector * stationBikes, vector * graph) { bool* visited = new bool[stationNum]; // 保存是否访问过 vector * pre = new vector [stationNum]; // 保存每个站点的前序节点 int* pathLength = new int[stationNum]; // 保存0到每个站点的路径长度 for (int i = 0; i < stationNum; i++) { visited[i] = false; pre[i].clear(); pathLength[i] = INF; } visited[0] = true; pathLength[0] = 0; bool hasUnvisited = true; for (int i = 0; i < graph[0].size(); i++) { pre[graph[0][i].end].push_back(0); pathLength[graph[0][i].end] = graph[0][i].length; } while (hasUnvisited) { hasUnvisited = false; int NextNode = 0, min = INF; // 对所有节点,找未访问过的最小路径点 for (int i = 1; i < stationNum; i++) { if (visited[i] == false && pathLength[i] < min) { min = pathLength[i]; NextNode = i; hasUnvisited = true; } } if (hasUnvisited == false || visited[problemIndex] == true) { // 剩余节点不连通或者全部节点已访问, // 或者 有问题的那个节点已经被访问了 break; } vector paths = graph[NextNode]; visited[NextNode] = true; for (int i = 0; i < paths.size(); i++) { if (visited[paths[i].end] == false && paths[i].length < INF) { if (paths[i].length + pathLength[NextNode] < pathLength[paths[i].end]) { // 起点的最短路径+当前路径长< 之前的终点的长,更新最短路径 pathLength[paths[i].end] = paths[i].length + pathLength[NextNode]; pre[paths[i].end].clear(); pre[paths[i].end].push_back(NextNode); } else if (paths[i].length + pathLength[NextNode] == pathLength[paths[i].end]) { pre[paths[i].end].push_back(NextNode); } } } } //打印一下路径前序 vector path; dfs(pre, 0, problemIndex, stationBikes, &path); cout << minNeed<<" "; for (int i = pathSave.size()-1; i >=0; i--) { cout << pathSave[i]; if (i>=1) { cout << "->"; } } cout <<" " << minRemain; } void dfs(vector * pre, int start, int end, vector * stationBikes, vector * path) { if (end==0) { path->push_back(end); // 叶子节点: int need = 0, remain = 0; for (int i = path->size()-1; i >=0; i--) { int id = (*path)[i]; if ((*stationBikes)[id]>0) { remain += (*stationBikes)[id]; } else { if (remain>abs((*stationBikes)[id])) { remain-=abs((*stationBikes)[id]); } else { need+=abs((*stationBikes)[id])-remain; remain = 0; } } } if (need minNeed = need; minRemain = remain; pathSave = *path; } else if (need == minNeed && remain minRemain = remain; pathSave = *path; } (*path).pop_back(); return; } (*path).push_back(end); vector pathEnd = pre[end]; for (int i = 0; i < pathEnd.size(); i++) { dfs(pre,start, pathEnd[i],stationBikes,path); } (*path).pop_back(); } int main() { int capicity, stationNum, problemIndex, paths; cin >> capicity >> stationNum >> problemIndex >> paths; int leftNum; vector stationBikes; stationBikes.push_back(0); for (int i = 0; i < stationNum; i++) { cin >> leftNum; stationBikes.push_back(leftNum-capicity/2); } int aim, end, length; vector * graph = new vector [stationNum + 1]; for (int i = 0; i < paths; i++) { cin >> aim >> end >> length; graph[aim].push_back(Path(end, length)); graph[end].push_back(Path(aim, length)); } Dijtra( stationNum + 1, problemIndex, &stationBikes, graph); }



