首页 > 试题广场 >

权值最大的路径

[编程题]权值最大的路径
  • 热度指数:541 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给出一个有向无环图,规定路径是单向且小序号指向大序号,每个节点都有权值。在图上求一条路径使得经过的节点权值和最大,输出路径

示例1

输入

[5,10,20,5,4,5],[[1,2],[1,4],[2,4],[3,4],[4,5],[4,6],[5,6]]

输出

"3-4-5-6"

说明

很明显 先去第三点权值为20,再去第四个点权值为5,再去第五个点权值为4,再去第六个点权值为5。这个方案最优 
class Solution {
public:
  /**
   * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
   *
   * 
   * @param potatoNum intvector 依次表示序号为1,2,3..的节点的权值
   * @param connectRoad intvector<vector<>> 每个一维数组[x,y]表示从第x号到第y号有路
   * @return string
   */
  string digSum(vector<int>& potatoNum, vector<vector<int> >& connectRoad) {
    const int n = potatoNum.size();
    vector<vector<int>> g(n + 1);
    for (const auto& c : connectRoad)
      g[c[0]].emplace_back(c[1]);
    
    function<pair<int, string>(int)> dfs = [&](int u) {
      if (memo_.find(u) != end(memo_))
        return memo_.at(u);
      
      if (g[u].empty()) // leaf node case
        return memo_[u] = make_pair(potatoNum[u - 1], to_string(u));
      
      string path;
      int weight = 0;
      for (const int nxt : g[u]) {
        auto [w, p] = dfs(nxt);
        if (w > weight) {
          path = p;
          weight = w;
        }
      }
      
      return memo_[u] = make_pair(potatoNum[u - 1] + weight, to_string(u) + '-' + path);
    };
    
    string ans;
    int weight = 0;
    for (int u = 1; u <= n; ++u) {
      const auto [w, path] = dfs(u);
      if (w > weight) {
        weight = w;
        ans = path;
      }
    }
    
    return ans;
  }
  
private:
  unordered_map<int, pair<int, string>> memo_;
};

发表于 2021-07-17 09:55:55 回复(0)
用map<int,vector<int>>记录下每个节点的下一跳集合
然后从后往前依次 分析每一个坑,更新每个坑开始的最大值
以及取得最大值时下一条的index   
最后回溯即可
 string digSum(vector<int>& potatoNum, vector<vector<int> >& connectRoad) {
        // write code here
        int dp[251]={0};
        int trace[251];
        for(int i=0;i<potatoNum.size();i++)
        {
               dp[i+1]=potatoNum[i];
               trace[i+1]=i+1;  
            
        }
        map<int,vector<int>> roads;
        for(int i=0;i<connectRoad.size();i++)
        {
            if(roads.find(connectRoad[i][0])!=roads.end()) //没找到
            {
                roads[connectRoad[i][0]].push_back((connectRoad[i][1]));
            }
            else
            {
                vector<int> one;
                one.push_back(connectRoad[i][1]);
                roads[connectRoad[i][0]]=one;
                
            }
            
        }
        
        int ans=dp[potatoNum.size()];
        int index=potatoNum.size();
        
        for(int i=potatoNum.size();i>=1;i--)
        {
            
            if(roads.find(i)==roads.end())//没有下一条
            {
                if(dp[i]>ans)
                {
                    ans=dp[i];
                    index=i;
                }
                
            }
            else
            {
                int max_=0;
                int next=0;
                for(int k=0;k<roads[i].size();k++)
                {
                    if(max_<dp[roads[i][k]])
                    {
                        max_=dp[roads[i][k]];
                        next=roads[i][k];
                    }
                }
                dp[i]+=max_;
                trace[i]=next; //记录下下一条位置
                if(dp[i]>ans)
                {
                    ans=dp[i];
                    index=i;
                    
                }
                
                
                
            }
            
            
            
        }
        
        
        //从index处往后迭代
        string res;
        while(trace[index]!=index)
        {
            res+=to_string(index);
            res+='-';
            index=trace[index];
        }
        res+=to_string(index);
         
        return res;
        
        
    }


发表于 2020-09-26 00:35:00 回复(0)
class Solution {
public:
    /**
     * 
     * @param potatoNum int整型vector 依次表示序号为1,2,3..的番薯洞各有多少个番薯
     * @param connectRoad int整型vector<vector<>> 每个一维数组[x,y]表示从第x号番薯洞到第y号有路
     * @return string字符串
     */
    string digSum(vector<int>& potatoNum, vector<vector<int> >& connectRoad) {
        // write code here
        int sz = potatoNum.size();
        vector<vector<int> > path(sz +1);    // 存路径,从后往前存
        for(auto e: connectRoad){
            path[e[1]].push_back(e[0]);
        }
        vector<pair<int,int>> dp(sz+1);    // 每个节点  可摘取的最大数量,以及路径的前一个节点
        dp[0] = {0,0};
        for(int i=1;i<sz+1;i++){
            pair<int,int> Maxtemp = {0,0};
            for(int j=0;j<path[i].size();j++){
                if(dp[path[i][j]].first > Maxtemp.first){
                    Maxtemp.first = dp[path[i][j]].first;
                    Maxtemp.second = path[i][j];
                }
            }
            dp[i] = {Maxtemp.first+potatoNum[i-1],Maxtemp.second};
        }
        
        int maxnum = 0;    //最大可采摘数量
        int maxindex = 0;    // 最大可采摘数量对应的节点
        for(int i = 0;i<sz+1;i++){
            if(dp[i].first>maxnum){
                maxnum = dp[i].first;
                maxindex = i;
            }
        }
        
        vector<int> resint; 
        
        while(maxindex!=0){
            resint.push_back(maxindex);
            maxindex = dp[maxindex].second;
        }
        
        string res;
        for(int i =resint.size()-1;i>=0;i--){
            string s = to_string(resint[i]);
            res.append(s);
            if(i!=0){
                res.append("-");
            }  
        }
        return res;
    }
};

发表于 2020-08-13 11:56:08 回复(0)
//该方法遍历深度较大,所以只过了80%,剩下的超时了,实在想不出哪里可以剪枝
//望大佬提供一下剪枝四路
class Solution {
public:
    void find(vector<int>& potatoNum, vector<vector<int> >& connectRoad,int i,int tmp)
    {
        tmp+=potatoNum[i - 1];//累加到达当前洞口中的番茄个数
        part.push_back(i);//存入当前路劲
                //循环遍历找当前洞口联通的下一个洞口
        for(int k = 0;k<connectRoad.size();k++)
        {
            if(connectRoad[k][0] == i)//找到了
                find(potatoNum,connectRoad,connectRoad[k][1],tmp);//进入该洞口
        }
                //当走到这里时,表示到达了当前路劲的尽头,判断当前路劲下取得番茄个数是否大于
                //max,如果大于,则番茄个数交换,最佳路径交换
        if(tmp > max)
        {
          best_part = part;
          max = tmp;
        }
                //当前路劲返回上一层,继续寻找下一个联通的洞穴
        part.pop_back();
    }
    string digSum(vector<int>& potatoNum, vector<vector<int> >& connectRoad) {
        // write code here
                //分别从每个洞口开始找
        for(int i = 1;i<potatoNum.size() + 1;i++)
        {
            find(potatoNum,connectRoad,i,0);
        }
                //以下是返回string
        string str("");
        for(int i = 0;i<best_part.size();i++)
        {
            int tmp = best_part[i];
            stringstream ss;
            ss<<tmp;
            str+=ss.str();
            if(i != best_part.size() - 1)
                str+="-";
        }
        return str;
    }
public:
    vector<int> part;//当前路径
    vector<int> best_part;//取得最多番茄个数的路径
    int max = 0;//番茄最多个数
};

发表于 2020-07-25 19:07:22 回复(2)

问题信息

难度:
4条回答 2900浏览

热门推荐

通过挑战的用户

查看代码