• 某车企笔试题解答(1)


    目录

    题目:

    答:

    1建立数学模型

    2求解


    题目:

    一个简易吃豆人游戏,假设有一个m*n的棋盘(0

    答:

    解答本题分如下两步:1建立数学模型;2求解。

    1建立数学模型

    将这个m*n的棋盘(左图)抽象为图论中的有向无环图(缩写为DAG,右图)。

    棋盘中的每个格子对应有向无环图的一个顶点,指向该顶点的边的权重等于该顶点的豆子数(比如,指向棋盘格子b的边,权重等于b,以此类推)。由于吃豆人只能向右或者向下移动,所以水平方向的边只能从左向右,垂直方向的边只能从上到下,如上图所示。由于这个限制,导致从任何一点出发,不论采取何种路径,都不会回到出发点,所以这个图是无环图。

    由于棋盘中的每个格子对应有向无环图的一个顶点,所以有向无环图的水平方向的顶点数等于棋盘水平方向的格子数m,而水平方向的边数比顶点数少1,所以是m-1;有向无环图的垂直方向的顶点数等于棋盘垂直方向的格子数n,所以有向无环图的垂直方向的顶点数是n,垂直方向的边数是n-1。顶点总数为m*n。而边总数为(m-1)*(n-1)。

    搜索吃豆人吃豆最多路线的问题就变成了搜索DAG最长路径的问题。此类问题的复杂度是O(边数+顶点数),故为O(m*n)

    2求解

    Longest Path in a Directed Acyclic Graph - GeeksforGeeks提供了示例代码解决此类问题。在此示例基础上略作修改,考虑如下棋盘,其格子中的数字代表格子内豆子数目:

     

    根据前面的分析,数学模型对应一个顶点数为4 * 3= 12的DAG。

    采用如下代码求解:

    1. // A C++ program to find single source longest distances
    2. // in a DAG
    3. #include
    4. #include
    5. #include
    6. #include
    7. #define NINF INT_MIN
    8. using namespace std;
    9. // Graph is represented using adjacency list. Every
    10. // node of adjacency list contains vertex number of
    11. // the vertex to which edge connects. It also
    12. // contains weight of the edge
    13. class AdjListNode {
    14.     int v;
    15.     int weight;
    16. public:
    17.     AdjListNode(int _v, int _w)
    18.     {
    19.         v = _v;
    20.         weight = _w;
    21.     }
    22.     int getV() { return v; }
    23.     int getWeight() { return weight; }
    24. };
    25. // Class to represent a graph using adjacency list
    26. // representation
    27. class Graph {
    28.     int V; // No. of vertices'
    29.     // Pointer to an array containing adjacency lists
    30.     list* adj;
    31.     list<int>        *   pPath;
    32.     // A function used by longestPath
    33.     void topologicalSortUtil(int v, bool visited[],
    34.         stack<int>& Stack);
    35. public:
    36.     Graph(int V); // Constructor
    37.     ~Graph(); // Destructor
    38.     // function to add an edge to graph
    39.     void addEdge(int u, int v, int weight);
    40.     // Finds longest distances from given source vertex
    41.     void longestPath(int s);
    42. };
    43. Graph::Graph(int V) // Constructor
    44. {
    45.     this->V = V;
    46.     adj = new list[V];
    47.     pPath = new list<int>[V];
    48. }
    49. Graph::~Graph() // Destructor
    50. {
    51.     delete[] adj;
    52.     delete[] pPath;
    53. }
    54. void Graph::addEdge(int u, int v, int weight)
    55. {
    56.     AdjListNode node(v, weight);
    57.     adj[u].push_back(node); // Add v to u's list
    58. }
    59. // A recursive function used by longestPath. See below
    60. // link for details
    61. // https:// www.geeksforgeeks.org/topological-sorting/
    62. void Graph::topologicalSortUtil(int v, bool visited[],
    63.     stack<int>& Stack)
    64. {
    65.     // Mark the current node as visited
    66.     visited[v] = true;
    67.     // Recur for all the vertices adjacent to this vertex
    68.     list::iterator i;
    69.     for (i = adj[v].begin(); i != adj[v].end(); ++i) {
    70.         AdjListNode node = *i;
    71.         if (!visited[node.getV()])
    72.              topologicalSortUtil(node.getV(), visited, Stack);
    73.     }
    74.     // Push current vertex to stack which stores topological
    75.     // sort
    76.     Stack.push(v);
    77. }
    78. // The function to find longest distances from a given vertex.
    79. // It uses recursive topologicalSortUtil() to get topological
    80. // sorting.
    81. void Graph::longestPath(int s)
    82. {
    83.     stack<int> Stack;
    84.     int * dist = new int[V];
    85.     // Mark all the vertices as not visited
    86.     bool* visited = new bool[V];
    87.     for (int i = 0; i < V; i++)
    88.         visited[i] = false;
    89.     // Call the recursive helper function to store Topological
    90.     // Sort starting from all vertices one by one
    91.     for (int i = 0; i < V; i++)
    92.         if (visited[i] == false)
    93.              topologicalSortUtil(i, visited, Stack);
    94.     // Initialize distances to all vertices as infinite and
    95.     // distance to source as 0
    96.     for (int i = 0; i < V; i++)
    97.     {
    98.         pPath[s].clear();
    99.         dist[i] = NINF;
    100.     }
    101.        
    102.     dist[s] = 0;
    103.     pPath[s].push_back(s);
    104.     // Process vertices in topological order
    105.     while (Stack.empty() == false) {
    106.         // Get the next vertex from topological order
    107.         int u = Stack.top();
    108.         Stack.pop();
    109.         // Update distances of all adjacent vertices
    110.         list::iterator i;
    111.         if (dist[u] != NINF) {
    112.              for (i = adj[u].begin(); i != adj[u].end(); ++i)
    113.              {
    114.                  if (dist[i->getV()] < dist[u] + i->getWeight())
    115.                  {
    116.                      //更新与u相连的各个顶点到s的距离
    117.                      dist[i->getV()] = dist[u] + i->getWeight();
    118.                      //更新具体路径
    119.                      pPath[i->getV()].assign(pPath[u].begin(), pPath[u].end());
    120.                      pPath[i->getV()].push_back(i->getV());
    121.                  }  
    122.              }
    123.         }
    124.     }
    125.     // Print the calculated longest distances
    126.     for (int i = 0; i < V; i++)
    127.     {
    128.         cout << "length: ";
    129.         (dist[i] == NINF) ? cout << "unReachable" : cout << dist[i];
    130.         cout<< endl;
    131.         cout << "path: ";
    132.         for (const auto & item : pPath[i])
    133.         {
    134.              cout << item << " ";
    135.         }
    136.         cout << endl;
    137.     }
    138.        
    139.     delete [] visited;
    140.     delete [] dist;
    141.     delete [] pPath;
    142. }
    143. // Driver program to test above functions
    144. int main()
    145. {
    146.     // Create a graph given in the above diagram.
    147.     Graph g(12);
    148.     g.addEdge(0, 1, 1);
    149.     g.addEdge(0, 4, 3);
    150.     g.addEdge(1, 2, 2);
    151.     g.addEdge(1, 5, 5);
    152.     g.addEdge(2, 3, 4);
    153.     g.addEdge(2, 6, 1);
    154.     //g.addEdge(3, 4, 0);//3号顶点处于棋盘最右
    155.     g.addEdge(3, 7, 2);
    156.     g.addEdge(4, 5, 5);
    157.     g.addEdge(4, 8, 1);
    158.     g.addEdge(5, 6, 1);
    159.     g.addEdge(5, 9, 1);
    160.     g.addEdge(6, 7, 2);
    161.     g.addEdge(6, 10, 3);
    162.     //g.addEdge(7, 8, 0);//7号顶点处于棋盘最右,不能再向右了
    163.     g.addEdge(7, 11, 2);
    164.     g.addEdge(8, 9, 1);
    165.     //g.addEdge(8, 8, 1);
    166.     g.addEdge(9, 10, 3);
    167.     //g.addEdge(9, 9, 1);
    168.     g.addEdge(10, 11, 2);
    169.     //g.addEdge(10, 10, 3);
    170.     //g.addEdge(11, 8, 0);//11号顶点处于棋盘最右,不能再向右了
    171.     //g.addEdge(11, 11, 2); //11号顶点处于棋盘最下
    172.     int s = 0;
    173.     cout << "Following are longest distances from "
    174.         "source vertex "
    175.         << s << " \n";
    176.     g.longestPath(s);
    177.     cin.get();
    178.     return 0;
    179. }

    在上面的问题中,采用0-11标记棋盘的格子:

     

    结果:

    可见,最长路径是0-4-5-9-10-11,长度为14

     

    算法的时间复杂度为O(顶点数+边数)。这里也就是O(m*n)

  • 相关阅读:
    `英语` 2022/8/22
    springboot使用redis实现消息队列功能,redis使用list和stream实现消息队列功能,redis实现消息队列的风险点分析
    Nginx之带宽限制解读
    139 单词拆分
    猿创征文 | Docker实战:Linux环境安装Tomcat安装步骤
    Leetcode2918. 数组的最小相等和
    会议OA之待开会议&所有会议
    [附源码]计算机毕业设计JAVA电子交易平台
    机器人控制——C++ HSM状态机基础知识
    面试官:Redis的各项功能解决了哪些问题?
  • 原文地址:https://blog.csdn.net/liji_digital/article/details/127845345