• LeetCode 847. Shortest Path Visiting All Nodes


    题目链接:https://leetcode.com/problems/shortest-path-visiting-all-nodes/

    题意:已知一条无向图,问经过所有点的最短路径是多长,边权都为1,每个点可能经过多次。

    这道题写的时候想简单了,把它当成树的直径来做了,求出一条最长路径len(len上的点只经过一次),2*(点数-1)-len即为答案,竟然过了,后来看了看讨论区发现这不是正解,而且我也没办法证明,感觉是蒙对的。贴下代码:

    class Solution {
    public:
    	void dfs(bool &f,int x, int sum, vector<vector<int>>& graph, int &ans, int vis[]) {
    		if (f)
    			return ;
    		if (sum == graph.size()-1) {  //不加这个剪枝还会TLE,加了以后快的飞起,因为存在全连接图
    			f = 1;
    			ans = sum;
    			return ;
    		}
    		vis[x] = 1;
    		for (int i = 0;i < graph[x].size();i++) {
    			if (vis[graph[x][i]] == 0) {
    				dfs( f,graph[x][i], sum + 1, graph, ans, vis);
    				vis[graph[x][i]] = 0;
    			}
    		}
    		ans = max(sum, ans);   //ans为图中的最长路径(路径上的点只经过一次)
    	}
    	int shortestPathLength(vector<vector<int>>& graph) {
    		if (graph[0].size() == 0)
    			return 0;
    		int vis[15];
    		memset(vis, 0, sizeof(vis));
    		int ans = 0;
    		bool f = 0;
    		for (int i = graph.size()-1;i>=0&&!f;i--) {
    			memset(vis, 0, sizeof(vis));
    			dfs(f,i, 0, graph, ans, vis);
    		}
    
    		cout << ans << -1 << endl;
    		return (graph.size() - 1) * 2 - ans;
    	}
    }; 

    正解应该是状压dp:

     dp[i][j]表示当前在第i个节点,且已经走过的节点集合为j用二进制表示时1的位置,从u到v,$dp[v][j|(1<<v)] = min(dp[v][j],dp[u][j]+1);$(dp[u][j]为在u点的状态),bfs不断更新即可

    class Solution {
    public:
    	int shortestPathLength(vector<vector<int>>& graph) {
    		vector<vector<int> > dp(graph.size(),vector<int>((1<<graph.size()),1e9) );
            queue<pair<int,int> > q;   //使用队列存储dp值
            for(int i=0;i<graph.size();i++){
                dp[i][1<<i]=0;
                q.push(make_pair(i,1<<i));
            }
            while(!q.empty()){
                pair p = q.front();
                q.pop();
                for(int i=0;i<graph[p.first].size();i++){
                    int v=graph[p.first][i];
                    if(dp[v][p.second|(1<<v)]>dp[p.first][p.second]+1){  //比当前优则入队
                        dp[v][p.second|(1<<v)] = dp[p.first][p.second]+1;
                        q.push(make_pair(v,p.second|(1<<v)));
                    }
                }
            }
            int ans=1e9;
            for(int i=0;i<graph.size();i++)
                ans=min(ans,dp[i][(1<<graph.size())-1]);
            return ans;
    	}
    };
    

      

  • 相关阅读:
    侯捷STL课程及源码剖析学习1
    路边拾遗之其他模块(struct/csv/xlwt/smtp)
    面向对象之内置方法(简单)、组合。以及接口归一化设计与抽象类
    面向对象之继承与派生
    面向对象之类属性实例属性及其增删改查
    python中常用模块详解二
    函数之命名空间、作用域、闭包、装饰器四剑客。
    文件操作之1,2,3
    python中常用模块详解一
    python内置常用内置方法详解
  • 原文地址:https://www.cnblogs.com/dlutjwh/p/10935110.html
Copyright © 2020-2023  润新知