leetcode:LCP 07. 传递信息

题目描述

题目解析

这道题是算法:机器人必须走 K 步,最终能来到P位置的方法有多少种的升级版

思路: 先生成一个图,然后递归求解

struct Node;
struct Edge;
struct Graph;

struct Node{
    int val;
    int in;
    int out;
    std::vector<std::shared_ptr<Node>> nexts;
    std::vector<std::shared_ptr<Edge>> edges;
    
    explicit Node(int val, int in = 0, int out = 0) : val(val), in(0), out(0){
        
    }
};

struct Edge{
    int weight;
    std::shared_ptr<Node> from;
    std::shared_ptr<Node> to;
    
    explicit Edge(int w,  std::shared_ptr<Node>&f,  std::shared_ptr<Node>& t) : weight(w), from(f), to(t) {
        
    }
};

struct Graph{
    std::map<int, std::shared_ptr<Node>> nodes;
    std::set<std::shared_ptr<Edge>>  edges;
};




class Solution {
    static std::shared_ptr<Graph> createGraph(vector<vector<int>>& relation){
        std::shared_ptr<Graph> graph = std::make_shared<Graph>();
        int N = relation.size();
        for (int i = 0; i < N; ++i) {
            int fromLabel = relation[i][0], toLabel = relation[i][1];
            if(!graph->nodes.count(fromLabel)){
                graph->nodes[fromLabel] = std::make_shared<Node>(fromLabel);
            }
            if(!graph->nodes.count(toLabel)){
                graph->nodes[toLabel] = std::make_shared<Node>(toLabel);
            }
            auto fromNode = graph->nodes[fromLabel], toNode = graph->nodes[toLabel];
            std::shared_ptr<Edge> newEdge = std::make_shared<Edge>(0, fromNode, toNode);
            fromNode->out++;
            toNode->in--;
            fromNode->nexts.emplace_back(toNode);
            fromNode->edges.emplace_back(newEdge);
            graph->edges.emplace(newEdge);
        }
        return graph;
    }
    
    int walkPath(std::shared_ptr<Node> &start, std::shared_ptr<Node> &end, int k){
        if(k == 0){
            return start == end ? 1 : 0;
        }
        
        int ways = 0;
        for(auto node : start->nexts){
            ways += walkPath(node, end, k - 1);
        }
        return ways;
    }
    
public:
    int numWays(int n, vector<vector<int>>& relation, int k) {
        if(relation.empty() || k < 0){
            return 0;
        }
        std::shared_ptr<Graph>  graph = createGraph(relation);
        std::shared_ptr<Node> start = graph->nodes[0];
        std::shared_ptr<Node> end = graph->nodes[n - 1];
        if(start == nullptr || end == nullptr){
            return 0;
        }
        
        return walkPath(start, end, k);
    }
};

在这里插入图片描述

备忘录

#include <vector>
#include <map>
#include <vector>
#include <memory>
#include <stack>
#include <set>
#include <queue>
#include <iostream>


using namespace std;

struct Node;
struct Edge;
struct Graph;

struct Node{
    int val;
    int in;
    int out;
    std::vector<std::shared_ptr<Node>> nexts;
    std::vector<std::shared_ptr<Edge>> edges;
    
    explicit Node(int val, int in = 0, int out = 0) : val(val), in(0), out(0){
        
    }
};

struct Edge{
    int weight;
    std::shared_ptr<Node> from;
    std::shared_ptr<Node> to;
    
    explicit Edge(int w,  std::shared_ptr<Node>&f,  std::shared_ptr<Node>& t) : weight(w), from(f), to(t) {
        
    }
};

struct Graph{
    std::map<int, std::shared_ptr<Node>> nodes;
    std::set<std::shared_ptr<Edge>>  edges;
};




class Solution {
    static std::shared_ptr<Graph> createGraph(vector<vector<int>>& relation){
        std::shared_ptr<Graph> graph = std::make_shared<Graph>();
        int N = relation.size();
        for (int i = 0; i < N; ++i) {
            int fromLabel = relation[i][0], toLabel = relation[i][1];
            if(!graph->nodes.count(fromLabel)){
                graph->nodes[fromLabel] = std::make_shared<Node>(fromLabel);
            }
            if(!graph->nodes.count(toLabel)){
                graph->nodes[toLabel] = std::make_shared<Node>(toLabel);
            }
            auto fromNode = graph->nodes[fromLabel], toNode = graph->nodes[toLabel];
            std::shared_ptr<Edge> newEdge = std::make_shared<Edge>(0, fromNode, toNode);
            fromNode->out++;
            toNode->in--;
            fromNode->nexts.emplace_back(toNode);
            fromNode->edges.emplace_back(newEdge);
            graph->edges.emplace(newEdge);
        }
        return graph;
    }
    
    std::map<std::string, int> map;
    int walkPath(std::shared_ptr<Node> &start, std::shared_ptr<Node> &end, int k){
        std::string key = std::to_string(start->val) + "_" + std::to_string(end->val) + "_" + std::to_string(k);
        if(map.count(key)){
            return map[key];
        }

        int ways = 0;
        if(k == 0){
            ways =  start == end ? 1 : 0;
        }else{
            for(auto node : start->nexts){
                ways += walkPath(node, end, k - 1);
            }
        }
        map[key] = ways;
        return ways;
    }
    
public:
    int numWays(int n, vector<vector<int>>& relation, int k) {
        if(relation.empty() || k < 0){
            return 0;
        }
        std::shared_ptr<Graph>  graph = createGraph(relation);
        std::shared_ptr<Node> start = graph->nodes[0];
        std::shared_ptr<Node> end = graph->nodes[n - 1];
        if(start == nullptr || end == nullptr){
            return 0;
        }
        
        return walkPath(start, end, k);
    }
};

在这里插入图片描述

暴力递归改动态规划

(1)准备表,主要通过分析可变参数的取值范围得到

int walkPath(std::shared_ptr<Node> &start, std::shared_ptr<Node> &end, int k)
  • start:取值范围----start--end-----0---n - 1
  • k:取值范围------0~k

所以准备一个二维数组:

std::vector<std::vector<int>> dp[n][k + 1];

(2)分析返回值,主要看主函数是怎么调用

        return walkPath(start, end, k);  // walkPath(0, n - 1, k);

所以应该返回dp[0][k]

(3)开始填表

(3.1)base case,也就是表初始化

 if(k == 0){
            return start == end ? 1 : 0;
        }
  • 从上面可以看出,需要填写k = 0时
dp[0][0] = 1;  // 开始位置为0,而且不需要走路

(3.2)分析普通情况

  • 先看依赖
    	 for(auto node : start->nexts){
                ways += walkPath(node, end, k - 1);
            }
  • 从上面可以看出:

待续…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值