这是我遇到的一个非常有趣的问题:有一个有向树,每个节点的权重随时间变化,我必须找到从根到某个节点的距离。
问题陈述:
从队列到达计数器的预计时间取决于该队列中的人数加上其他队列中的人数。
例如,如果有2个队列中每个包含3个粉丝,则队列1中的前导人员将首先发送,然后是队列2中的前导人员,接着是队列1中的下一个人员,依此类推。它是传入队列之间的备用选择。
对于给定输入
计算一个人到达即将进入任何队列的故障单计数器的最短时间。此外,在最坏的情况下,输出他应该在最短时间内到达柜台的路径(在每个交叉点,警察开始从队列中选择人员而不是我们正在计算的人员最短时间)。
如何解决这类时变问题?
例如:
7
6
1 5 9
2 5 5
3 6 1
4 6 3
5 7 7
6 7 4
答案 0 :(得分:5)
通过从每个入口节点(离开)到出口节点(root)找到最短路径,可以解决此问题。
在我下面的实现中,我使用了一个邻接矩阵来表示那种(有向)图,但是你可以把它想象成一个二叉树(因为这个问题为每个连接定义了最多2个输入队列)。
int shortestPath(root)
if (both childs exists)
return min(shortestPath(node->left),shortestPath(node->right))*2+1
if (left child exists)
return shortestPath(node->left)
if (right child exists)
return shortestPath(node->right)
return 0; //no childs
正常最短路径与此问题之间的唯一区别是,每当我们有两个传入队列时,警察会逐个地从每个队列中发送粉丝。这意味着为了通过该队列,将时间加倍。 +1是因为我们假设他从较长的队列路径开始。
这是一个有效的C ++代码,它返回一个包含最佳时间和路径的对。如果有多个最佳路径,它将只返回其中一个。
const pair<int,vector<int>>& min(const pair<int,vector<int>>& a, const pair<int,vector<int>>& b) {
return (a.first < b.first) ? a : b;
}
pair<int,vector<int>> findShortestPath(vector<vector<int>>& graph, int v){
vector<pair<int,vector<int>>> childs;
for (int i=0; i<v; i++){
if (graph[i][v] != -1){
pair<int,vector<int>> path = findShortestPath(graph,i);
path.second.push_back(v+1);
childs.push_back(make_pair(path.first + graph[i][v], path.second));
}
}
if (childs.size() == 2){
pair<int,vector<int>> path = min(childs[0],childs[1]);
return make_pair(path.first*2+1, path.second);
}
if (childs.size() == 1){
return make_pair(childs[0].first,childs[0].second);
}
else{
vector<int> start = {v+1};
return make_pair(0,start);
}
}
此代码的时间复杂度为O(n^2)
,其中n
是顶点数。您也可以使用邻接列表表示(=二叉树)在O(n)
中实现它。
为了完整性,这里还有main
用于从给定输入创建图形并打印最佳时间和路径。 See this live test of your example's input
int main()
{
int n, e;
cin >> n; //num of vertices
cin >> e; //num of queues
vector<vector<int>> graph;
//initialize graph matrix cells to -1
graph.resize(n);
for (int i=0;i<n;i++){
graph[i].resize(n);
for (int j=0;j<n;j++)
graph[i][j] = -1;
}
//add edges and their weights
for (int i=0;i<e;i++){
int s,d,val;
cin >> s >> d >> val;
graph[s-1][d-1] = val;
}
//run algorithm
pair<int,vector<int>> path = findShortestPath(graph, n-1);
//print results
cout << path.first << endl;
for (int i=0;i<path.second.size()-1;i++)
cout << path.second[i] << " -> ";
cout << path.second[path.second.size()-1] << endl;
return 0;
}
答案 1 :(得分:-2)
这应该通过动态编程来解决
设P(j)是人的位置,如果需要最佳风扇,则通过连接点j。例如,在你的情况下P(6)= 4,因为到达交叉点3的人将是第4个通过交叉点6(在P27,P26和P28之后)。
以下三个命题是显而易见的,并解决了这个问题
如果是一个&#34;交界点&#34; j是扇形,P(j)= 1(基本情况)
如果是一个&#34;交界点&#34; j是与子l和r的正确连接点,并且在r和j之间的队列中l和j之间的队列中有x个人,我们有P(j)= 2 * min(P(l) + x,P(r)+ y)
如果有人要通过柜台,那么到达那里需要n-1次
您可以轻松地使用DP和一些簿记(如果在左侧或右侧达到分钟),您可以获得最佳风扇。