LeetCode 847. Shortest Path Visiting All Nodes

这周lc比赛最后一题比较复杂拿出来说下

An undirected, connected graph of N nodes (labeled 0, 1, 2, ..., N-1) is given as graph.

graph.length = N, and j != i is in the list graph[i] exactly once, if and only if nodes i and j are connected.

Return the length of the shortest path that visits every node. You may start and stop at any node, you may revisit nodes multiple times, and you may reuse edges.



Example 1:

Input: [[1,2,3],[0],[0],[0]]
Output: 4
Explanation: One possible path is [1,0,2,0,3]
Example 2:

Input: [[1],[0,2,4],[1,3,4],[2],[1,2]]
Output: 4
Explanation: One possible path is [0,1,4,2,3]


Note:

1 <= graph.length <= 12
0 <= graph[i].length < graph.length

1.一开始的思路 – 能否在图中拿出一条最长的欧拉路 然后填上欧拉路中没有的点 每次添加一个ans+2

2.tle但是正确的解,从某个点开始dfs,ans= 搜到的最到深度+(总数-搜到的最大深度)*2

class Solution {
public:
    int ans ;
    map< pair< int ,int >  ,int > dp ;
    int  dfs( int u , vector < vector< int > >  & graph , int depth,map< int , int > & check ){
        int ans = 0 ; 
        for( int i=0 ; i< graph[u].size() ; i++){
            int v=  graph[u][i] ; 
            if( check[v] == 0 ){
                check[v]++;

                int t = 1 + dfs(  v, graph , depth+1 ,check ) ; 
                //dp[ {u,v} ] = t -1 ; 
                ans = max( ans , t ) ; 
                check[v]--;
            }
        }

        return ans ; 
    }
    int shortestPathLength(vector<vector<int>>& graph) {
        int n = graph.size() ; 
        int res = INT_MAX ;  

        for( int i=0 ; i< n ; i++){
            map< int , int > check ; 
            ans = 0 ; 
            check[i]++;
            int ans  = dfs( i , graph , 0 , check ) ; 
            int t = n -( ans + 1) ;  
            res = min ( res,  t*2 + ans ) ; 
        }

        return res ; 
    }
};

在上面的代码中我开了没有用到dp,想要通过记忆化搜索去ac代码

思路是如果这个点搜过了,并且知道它最大的深度直接加上最大深度即可

但是有个问题那就是进来的点需要判断是否在能搜到的最大深度的子集里

最后这题看了discuss 得知压缩dp通过S记录所有点的状态

dp[S][i] 代表着在 i 这个点的时候 ,我们搜了集合S中的状态

如果S的二进制是 10101代表 vertex 0,2,4 我们搜过了

如果此时的i为 1 如 dp[10101][1] 代表我们在 1 这个点时 ,搜掉10101所使用的最小代价

定义了状态 , 需要初始化dp

对于每个vertex应该有 dp[1 << i][i] = 0 因为我们不用走就已经可以得到S这个状态

接着是状态转移 和产生的代价

此处需要举个例子

如dp[11][0] 代表此时在0处集合为11的代价,那么他就应该满足

dp[11][0] = min( dp[11][0] , dp[10][1] + dis[1][0] ) 
class Solution {
public:
    int dp[1<<12][12];
    int dis[12][12] ; 
    void floyd( vector< vector< int> > & graph ){
        int n = graph.size(); 
        { //floyd algorithm
        //   init floyd algorithm
        for( int i =0 ; i < n; i++){
            for( int j =0 ; jfor( int i  =0 ; i< n; i ++){
            dis[i][i] = 0 ; 
        }
        for( int u = 0 ; ufor( auto & v : graph[u] ){
                dis[u][v] = 1 ;
                dis[v][u] = 1; 
            }
        }
        // get the table of dis[i][j] 
            for( int k =0 ; k< n ;k++){
                for( int i =0 ; ifor( int j=0 ; jif( k!=i && k!=j ){
                            dis[i][j] = min( dis[i][j] , dis[i][k] +dis[k][j] ) ; 
                        }
                    }
                }
            }
        }
    }
    int shortestPathLength(vector<vector<int>>& graph) {
        int n = graph.size() ; 
        floyd( graph ) ; 
        // init  dp array ;
        for( int i=0 ; i< n ; i++){
            for( int j=0 ; j<( 1<for( int i=0 ; i< n; i++){
            dp[1<0 ; 
        }
        for( int j=1 ; j<(1<for(int i=0;iif( j &(1<// now the ith vertex is actually in the Set j 
                    for( int k=0 ;k1<int res = 1<< 15 ; 
        for( int i=0 ; i< n; i++){
            res = min ( res , dp[(1<1][i] ) ; 
        }
        return res; 
    }
};

此处求点对的最短路使用的是floyd算法, 但是也可以使用n次bfs达到

你可能感兴趣的:(leetcode)