CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
山寨机中的战斗机! 程序优化工程师到底对IT界有没有贡献
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  专题开发/技术/项目 >  数据结构与算法

路径问题(c语言)

楼主darkwowowo(黑暗中呼啸)2002-03-05 17:42:03 在 专题开发/技术/项目 / 数据结构与算法 提问

寻找最有价值路径(c语言)  
   
  描述:  
   
  从上(入口)往下行走,直到最下节点(出口)结束,将所经节点上的数值相加,要求找到一条最有价值路径(既是路径总数值最大)并输出总数值。  
   
  图:  
   
  入口   ↓  
       ③  
       /\  
      ⑤     ④  
                /     \   /   \  
     ①     ②     ⑤  
                \   /     \   /  
                  ⑨     ⑧  
                    \     /  
                      ③  
  出口             ↓  
  输入文件:(abc.in)  
   
  第一行只有一个数n(1<=n<=199),且n为奇数,说明节点的层。从第二行到底n+1行为每一层中各节点的数值(在0和100之间),各个数用空格隔开,输入不要求判错。  
   
  输出文件:(abc.out)  
   
  只有一个数,为所求路径的价值数。  
   
  例子:  
   
  输入文件内容:  
  5  
  3  
  5   4  
  1   2   5  
  9   8  
  3  
  输出文件内容:  
  23 问题点数:100、回复次数:28Top

1 楼kbsoft(让世界充满爱!)回复于 2002-03-05 17:47:05 得分 0

这是求最长路径的题目嘛  
  Top

2 楼kbsoft(让世界充满爱!)回复于 2002-03-05 18:01:58 得分 5

以下为求一个有向无环图中最长的路径的算法,其它的问题你可以自行写出  
   
  int   maxlen,path[MAXSIZE];   //数组path用于存储当前路径  
  int   mlp[MAXSIZE];   //数组mlp用于存储已发现的最长路径    
   
  void   Get_Longest_Path(ALGraph   G{  
      maxlen=0;  
      FindIndegree(G,indegree);  
      for(i=0;i<G.vexnum;i++)  
      {  
          for(j=0;j<G.vexnum;j++)   visited[j]=0;  
          if(!indegree[i])   DFS(G,i,0);//从每一个零入度结点开始深度优先遍历  
      }  
      printf("Longest   Path:");  
      for(i=0;mlp[i];i++)   printf("%d",mlp[i]);   //输出最长路径  
  }//Get_Longest_Path    
   
  void   DFS(ALGraph   G,int   i,int   len)  
  {  
      visited[i]=1;  
      path[len]=i;  
      if(len>maxlen&&!G.vertices[i].firstarc)   //新的最长路径  
      {  
          for(j=0;j<=len;j++)   mlp[j]=path[j];   //保存下来  
          maxlen=len;  
      }  
      else  
      {  
          for(p=G.vertices[i].firstarc;p;p=p->nextarc)  
          {  
              j=p->adjvex;  
              if(!visited[j])   DFS(G,j,len+1);  
          }  
      }//else  
      path[i]=0;  
      visited[i]=0;  
  }//DFS    
   
  Top

3 楼birdinfly(birdinfly)回复于 2002-03-05 18:19:20 得分 0

可以看看运筹学,里面对这类问题讲的很深刻.Top

4 楼darkwowowo(黑暗中呼啸)回复于 2002-03-05 18:44:37 得分 0

看看例子,好像是每一层只能经过一次,否则的话,就不只23了。  
  还有,你帮我用tc作一下吧,顺便在加多点注释,那个输入也不好弄,因为每一行都要区分。^_^Top

5 楼sticker(了了)回复于 2002-03-05 19:37:02 得分 0

《数据结构》里尽是讲这种题的。Top

6 楼darkwowowo(黑暗中呼啸)回复于 2002-03-05 19:49:12 得分 0

谁帮我写一下啊???!!!Top

7 楼darkwowowo(黑暗中呼啸)回复于 2002-03-05 20:37:34 得分 0

有谁帮帮我啊?写个tc代码吧,各位老大。Top

8 楼LLnju(LLnju)回复于 2002-03-05 21:47:19 得分 90

to   darkwowowo:            
          你怎么一下问了这么多的问题,是不是老师布置的作业,什么问题都应该自己先想想,实在有什么不清楚了才来问问,这才是个办法。不要一出来就让人写代码,这样不好,有人告诉了你思路,程序最好还是自己写,不然   ......。  
          看你这个问题   "c或c++的输入输出问题"   实在是应该自己去看书。  
          这个问题   "超大整数开方问题(c语言)"   你至少应该先想想大概会用到些什么东东的,不要一出来就问人要代码。  
          在看看你的这个问题,就知道你根本没有想过这个问题,你这个问题中那个   图   的结构实在是简单了一些,用不着     kbsoft   写的   DFS   ,你看看这个东西:  
   
        an1     an2   ....   ann    
  an'1   an'2   an'3   ....   an'n  
   
  如果   已知   上面一层的最长路径了,下面一层的应该会吧   ,像   f(an'1)   =   f(an1)+an1   ,   f(an'2)   =   max(   f(an1)+an1   ,   f(an2)+an2)   )   .....   ,   这样一看就知道是个最标准的递归问题了。有了上面的就可以解决像:  
   
                                a11  
                            a21   a22  
                        a31   a32   a33  
   
                ...................      
               
          an1   an2   .............   ann    
   
  这样的图形了,你把下面的图翻过来,也是这样的一个图,不翻过来也可以用类似的想法处理,这样一来就简单了吧。  
   
  输入输出的问题最好不要问,自己看书解决吧,用   C   就注意   scanf,fscanf   ,   sscanf   ,   用   C++   就更简单   ,用熟   istream   ,   istringstring   ,   istrstream   就行了。Top

9 楼LLnju(LLnju)回复于 2002-03-05 21:53:47 得分 0

还有不要用   tc   了,用c/c++的话还是用   gcc   ,   vc.net   ,   vc   ,   bcb   吧,不然别人写的代码,你大概是不能通过的。Top

10 楼stoneyrh()回复于 2002-03-05 21:59:25 得分 0

高人一大堆,我还要继续努力Top

11 楼darkwowowo(黑暗中呼啸)回复于 2002-03-05 22:46:15 得分 0

我的思路是这样的,关于这个图的,首先要求是最短的路径,而且权值要最大,那肯定一层只能走一次(也必须走一次,否则无法到最下一层),那我是不是要把所有的路径找出来,再比较权值?这样计算量是不是太大了,不过好像算法简单一点,只要每找出一条路径,就把权值比较一次,最后最大的就是结果,还是有别的好方法?Top

12 楼darkwowowo(黑暗中呼啸)回复于 2002-03-05 22:55:51 得分 0

那这样,我每到一个节点,就把当前走过的路径权值算一下,只保留最大的全值的路径,这样可以减少运算次数。这样,其实每个节点最多只要比较两次,就是它左上方的和右上方的节点的权值与走过路径权值,把大的留下。可是就是写不出来。Top

13 楼sin4x(一瓶水)回复于 2002-03-05 23:21:13 得分 0

深度搜索,用一个全局的数组记录目前为止最有价值的  
  每次到最底的时候与其比较,更有价值则替换,  
  1<n<100的话,就这样应该就没问题了Top

14 楼LLnju(LLnju)回复于 2002-03-06 09:23:28 得分 0

不用DFS,看看上面的图怎么样求解。对上面的节点编号为:  
   
          a11  
      a21   a22  
  a31   a32   a33  
      a41   a42  
          a51  
   
          oo  
   
  记   f(x)   为   a11   到   x   的最长路径,不包括自己本身。  
   
  首先   :   f(a11)   =   0.   f(a21)=f(a22)=a11=3.  
   
  f(a31)=f(a21)+a21=8.   f(a32)=max(   f(a21)+a21   ,   f(a22)+a22   )   =   8.   f(a33)   =   f(a22)+a22   =   7.  
   
  f(a41)=max(f(a31)+a31,f(a32)+a32   )   =   10.   f(a42)=max(f(a32)+a32,f(a33)+a33)=12  
   
  f(a51)=max(f(a41)+a41,f(a42)+a42)=20  
   
  F   =   f(a51)+a51   =   23    
   
  用这种算法,算到1000层也没有问题,用   DFS   的话,50层就够呛。Top

15 楼darkwowowo(黑暗中呼啸)回复于 2002-03-06 10:19:17 得分 0

LLnju(LLnju)你说得很对,这种算法算到1000层也没问题,可是我要把它写出来就是写不出,给我写一段吧Top

16 楼starfish(海星)回复于 2002-03-06 17:22:13 得分 0

这种分层次的图的路径问题,可以用动态规划解决Top

17 楼Justin(兰色梧桐)回复于 2002-03-06 17:33:53 得分 5

给你个动态规划的源码:  
  /*  
    *   File:                 longest.c  
    *   Desciption:     动态规划算法计算网络的最长路线和最短路线  
    *   Created:           2001/12/2  
    *   Author:             Justin   Hou   [mailto:justin_hou@hotmail.com]  
    *  
    */  
  #include   <stdio.h>  
  #define     N     7                                                             /*   顶点数目           */  
  #define     I     999                                                         /*   表示无穷大       */  
   
  int   graph[N][N]   =   {                                                 /*   图的邻接矩阵   */  
                  {I,   4,   5,   8,   I,   I,   I},  
                  {I,   I,   I,   6,   6,   I,   I},  
                  {I,   I,   I,   5,   I,   7,   I},  
                  {I,   I,   I,   I,   8,   9,   9},  
                  {I,   I,   I,   I,   I,   I,   5},  
                  {I,   I,   I,   I,   I,   I,   4},  
                  {I,   I,   I,   I,   I,   I,   I}  
  };  
  int   List[N];                                                                 /*   存放拓扑序列   */  
   
  int   TopologicalOrder();                                           /*   拓扑排序函数   */  
   
  void   main()                                                                   /*   主   函   数           */  
  {  
                  int   i,   j,   k,   l;  
                  int   ee[N],   el[N];                                     /*   最长最短距离   */  
                  int   path_e[N][N],   path_l[N][N],   n_e[N],   n_l[N];  
                                                                                        /*   记录路径数据   */  
   
                  /*   初始化数据   */  
                  for   (i   =   0;   i   <   N;   i++)   {  
                                  n_e[i]   =   0;         /*   到   i   的最短路线的结点数   */  
                                  n_l[i]   =   0;         /*   到   i   的最长路线的结点数   */  
                                  ee[i]   =   I;  
                                  el[i]   =   0;  
                  }  
                  ee[0]   =   el[0]   =   0;           /*   初始化头结点   */  
                  path_e[0][0]   =   0;  
                  path_l[0][0]   =   0;  
                  n_e[0]   =   1;  
                  n_l[0]   =   1;  
   
                  /*   拓扑排序   */  
                  if   (!TopologicalOrder())  
                                  return;  
   
                  /*   对于拓扑序列,运用动态规划步步算出最长路线与最短路线   */  
                  for   (i   =   0;   i   <   N;   i++)   {  
   
                                  /*   提取拓扑序列的元素   */  
                                  k   =   List[i];  
                                  /*   更新它所指向顶点的所有数据   */  
                                  for   (j   =   0;   j   <   N;   j++)   {  
   
                                                  /*   寻找指向的顶点   */  
                                                  if   (graph[k][j]   !=   I)   {  
   
                                                                  /*   如果新路径更短   */  
                                                                  if   (graph[k][j]   +   ee[k]   <   ee[j])   {  
   
                                                                                  /*   更新最短路径长度   */  
                                                                                  ee[j]   =   graph[k][j]   +   ee[k];  
                                                                                  /*   更新最短路线   */  
                                                                                  for   (l   =   0;   l   <   n_e[k];   l++)   {  
                                                                                                  path_e[j][l]   =   path_e[k][l];  
                                                                                  }  
                                                                                  path_e[j][l]   =   j;  
                                                                                  n_e[j]   =   l   +   1;  
                                                                  }  
   
                                                                  /*   如果新路径更长   */  
                                                                  if   (graph[k][j]   +   el[k]   >   el[j])   {  
   
                                                                                  /*   更新最长路径长度   */  
                                                                                  el[j]   =   graph[k][j]   +   el[k];  
                                                                                  /*   更新最长路线   */  
                                                                                  for   (l   =   0;   l   <   n_l[k];   l++)   {  
                                                                                                  path_l[j][l]   =   path_l[k][l];  
                                                                                  }  
                                                                                  path_l[j][l]   =   j;  
                                                                                  n_l[j]   =   l   +   1;  
                                                                  }  
                                                  }  
                                  }  
                  }  
   
                  /*   输出结果到屏幕   */  
                  for   (i   =   0;   i   <   N;   i++)   {  
                                  printf("shortest(%d):   %2d           Path:   ",   i   +   1,   ee[i]);  
                                  for   (j   =   0;   j   <   n_e[i];   j++)   {  
                                                  printf("%d   ",   path_e[i][j]   +   1);  
                                  }  
                                  printf("\n");                  
                                  printf("longest   (%d):   %2d           Path:   ",   i   +   1,   el[i]);  
                                  for   (j   =   0;   j   <   n_l[i];   j++)   {  
                                                  printf("%d   ",   path_l[i][j]   +   1);  
                                  }  
                                  printf("\n");  
                  }  
  }  
   
  int   TopologicalOrder()  
  {  
                  int   i,   j,   top,   count;  
                  int   indegree[N],   Stack[N];  
   
                  top   =   0;                               /*   栈顶标志           */  
                  for   (i   =   0;   i   <   N;   i++)   {  
                                  indegree[i]   =   0;                   /*   初始化入度       */  
                                  for   (j   =   0;   j   <   N;   j++)   {  
                                                  if   (graph[j][i]   !=   I)   {       /*   如连通               */  
                                                                  indegree[i]++;         /*   入度自增1         */  
                                                  }  
                                  }  
                                  if   (!indegree[i]){                                 /*   如入度为零       */  
                                                  Stack[top++]   =   i;                   /*   入栈                   */  
                                  }  
                  }  
                  count   =   0;                                 /*   输出顶点数       */  
                  while   (top   !=   0)   {  
                                  i   =   Stack[--top];  
                                  List[count++]   =   i;  
                                  for   (j   =   0;   j   <   N;   j++)   {  
                                                  if   (graph[i][j]   !=   I)   {         /*   如连通               */  
                                                                  if   (!(--indegree[j]))   {     /*   而且入度为零   */  
                                                                                  Stack[top++]   =   j;       /*   入栈                   */  
                                                                  }  
                                                  }  
                                  }/*   for   */  
                  }/*   while   */  
   
                  return   (count   <   N)   ?   0   :   1;  
  }  
   
  Top

18 楼hssfox()回复于 2002-03-06 21:28:34 得分 0

kkTop

19 楼cntiger(阿汤)回复于 2002-03-07 10:53:01 得分 0

wonderfulTop

20 楼darkwowowo(黑暗中呼啸)回复于 2002-03-07 11:57:28 得分 0

还没看明白,正在琢磨。Top

21 楼cxwhust()回复于 2002-03-07 16:48:56 得分 0

我粗略看了一下,觉得解决方案基本上都是穷举法,显然受节点数量限制太大。有没有哪位老兄接触过“中国邮递员问题”?能否计算100个节点左右的最短路径呢?如有,请指教!先谢啦!Top

22 楼wgku(云霄)回复于 2002-03-07 18:58:11 得分 0

哇。。。。。。。。我还没看懂Top

23 楼LLnju(LLnju)回复于 2002-03-08 09:16:45 得分 0

给你一个可以直接运行的,O(n^2),   算到5000   层应该没有问题,呵呵。  
   
  #pragma   warning(disable:4786)  
   
  #include   <iostream>  
  #include   <fstream>  
  #include   <string>  
  #include   <vector>  
  #include   <cassert>  
  #include   <ctime>  
  #include   <string>  
  #include   <set>  
  using   namespace   std;  
   
  template<typename   _Ty>  
  const   _Ty   STDMAX(   const   _Ty&   __a   ,   const   _Ty&   __b   ){  
  return   __a   >=   __b   ?   __a   :   __b;   }  
   
  typedef pair<int,int> dtvalpair;  
  typedef vector<dtvalpair> laydt;  
  typedef vector<laydt> graphdt;  
   
  class   pathInfo    
  {  
  size_t depth;  
  graphdt graph;  
   
  public:  
  pathInfo()   :   depth(0)   {}  
  pathInfo(   size_t   dep   )   {   init(dep);   };  
  void   init(   size_t   dep   );  
  public:  
  laydt&   operator[]   (   size_t   index   )  
  {  
  assert(   index   <   depth   );  
  return   graph[index];  
  }  
  const   laydt&   operator[](   size_t   index   )   const  
  {  
  assert(   index   <   depth   );  
  return   graph[index];  
  }  
  public:  
  void rand()  
  {  
  srand(   static_cast<unsigned>(   time(NULL)   )   );  
  size_t mx   =   (   depth   +   1   )   /   2;  
  for(   int   i   =   0;   i   <   mx;   ++i   )  
  for(   int   j   =   0;   j   <=   i;   ++j   )    
  graph[i][j]   =   dtvalpair(   ::rand()   %   100   ,   0   );  
  for(   i   =   mx;   i   <   depth;   ++i   )  
  for(   int   j   =   0;   j   <   depth   -   i;   ++j   )  
  graph[i][j]   =   dtvalpair(   ::rand()   %   100   ,   0   );  
  }  
  void show(   ostream&   os   )   const  
  {  
  size_t mx   =   (   depth   +   1   )   /   2;  
  for(   int   i   =   0;   i   <   mx;   ++i   ){  
  for(   int   j   =   0;   j   <=   i;   ++j   )   {  
  os   <<   graph[i][j].first<<'('<<graph[i][j].second<<")\t";   }  
  os   <<   endl; }  
  for(   i   =   mx;   i   <   depth;   ++i   ){  
  for(   int   j   =   0;   j   <   depth   -   i;   ++j   ){  
  os   <<   graph[i][j].first<<'('<<graph[i][j].second<<")\t";   }  
  os   <<   endl;   }  
  }  
  void dump(   ostream&   os   ) //!   记录了求解过程,格式也符合输入文件的要求.  
  {  
  os   <<   depth   <<   endl   <<   endl;  
  size_t mx   =   (   depth   +   1   )   /   2;  
  for(   int   i   =   0;   i   <   mx;   ++i   ){  
  for(   int   j   =   0;   j   <=   i;   ++j   )   {  
  os   <<   graph[i][j].first<<   '\t';   }  
  os   <<   endl; }  
  for(   i   =   mx;   i   <   depth;   ++i   ){  
  for(   int   j   =   0;   j   <   depth   -   i;   ++j   ){  
  os   <<   graph[i][j].first<<   '\t';   }  
  os   <<   endl;   }  
   
  os   <<   endl   <<   endl   <<   "DUMP   INFO:"   <<   endl;  
  int   val   =   getValue(); show(   os   );  
  os   <<   endl   <<   endl   <<   "VAL:"   <<   val   <<   endl;  
  }  
  public:  
  int getValue()  
  {  
  size_t mx   =   (   depth   +   1   )   /   2;  
  graph[0][0].second = 0;  
   
  for(   int   i   =   1;   i   <   mx;   ++i   ){  
  graph[i][0].second   =   graph[i-1][0].first   +   graph[i-1][0].second;  
  for(   int   j   =   1;   j   <=   i   -   1;   ++j   )   {  
  graph[i][j].second   =   STDMAX(   graph[i-1][j-1].second   +   graph[i-1][j-1].first   ,  
  graph[i-1][j].second   +   graph[i-1][j].first   ); }  
  graph[i][i].second   =   graph[i-1][i-1].first   +   graph[i-1][i-1].second;   }  
   
  for(   i   =   mx;   i   <   depth;   ++i   )  
  for(   int   j   =   0;   j   <   depth   -   i;   ++j   )  
  graph[i][j].second   =   STDMAX(   graph[i-1][j].second   +   graph[i-1][j].first   ,    
  graph[i-1][j+1].second   +   graph[i-1][j+1].first   );    
  return graph[depth-1][0].first   +   graph[depth-1][0].second;  
  }  
  public:  
  friend   ostream&   operator   <<   (   ostream&   os   ,     pathInfo&   pi   ) {  
  return   os   <<   pi.getValue();   }  
  friend   istream&   operator   >>   (   istream&   is   ,   pathInfo&   pi   )     {  
  size_t dep; is   >>   dep; pi.init(   dep   );   int   dt;  
  assert(   dep   >=   3   &&   dep   &   1   );  
  size_t mx   =   (   pi.depth   +   1   )   /   2;  
  for(   int   i   =   0;   i   <   mx;   ++i   )  
  for(   int   j   =   0;   j   <=   i;   ++j   )   {    
  is   >>   dt;   pi[i][j]   =   dtvalpair(   dt   ,   0   );   }  
  for(   i   =   mx;   i   <   pi.depth;   ++i   )  
  for(   int   j   =   0;   j   <   pi.depth   -   i;   ++j   )   {  
  is   >>   dt;   pi[i][j]   =   dtvalpair(   dt   ,   0   );   }  
  return   is;  
  }  
  };  
   
  void   pathInfo::init(   size_t   dep   )  
  {  
  depth   =   dep;  
  graph.resize(   dep   );  
  assert(   dep   &   1   &&   dep   >=   3   );  
  for(   int   i   =   0;   i   <   dep;   ++i   )  
  graph[i].resize(   (   dep   +   1   )   /   2   );  
  }  
   
  void   test()  
  {  
  ofstream dumpDt("src.txt");  
  pathInfo pi(999);    
  pi.rand();   pi.dump(   dumpDt   );  
  }  
   
  void   main()  
  {  
  try   {  
  cout   <<   "TEST   pathInfo   BEGIN   ......"   <<   endl;  
  test(); //!  
  cout   <<   "TEST   pathInfo   END       ......"   <<   endl;  
  pathInfo pi;  
  cout   <<   "Input   filename:";  
  string   strFn; cin   >>   strFn;  
  ifstream is(   strFn.c_str()   );  
  is   >>   pi;  
  cout   <<   "VAL:"   <<   pi   <<   endl;  
  }  
  catch(...)  
  {  
  cerr   <<   "FATAL   ERROR"   <<   endl;  
  }  
  }Top

24 楼darkwowowo(黑暗中呼啸)回复于 2002-03-08 10:07:47 得分 0

LLnju(LLnju),谢谢你了,能给我加点注释吗?我重新开个贴子,ok?还有那个开方的问题,帮帮忙吧,星期一早上就要交了,而我实在是想不出来啊。我现在身边的数值分析的书又没有,你帮我一下啦,我还剩几百分,如果要分的话都给你了,要不然,就当我欠你啦。我的算法真的很不行。Top

25 楼darkwowowo(黑暗中呼啸)回复于 2002-03-08 10:29:16 得分 0

我在c/c++版里另外开个贴子了Top

26 楼airwjd(Nigle)回复于 2002-03-09 19:04:38 得分 0

收藏。Top

27 楼shajie(笨鸟先飞)回复于 2002-03-10 18:14:32 得分 0

这个问题太简单了!  
  Top

28 楼LeeMaRS(小菜虎,仍需努力)回复于 2002-03-12 00:23:07 得分 0

LLnju   能介绍一下你的算法么?   动态规划?Top

相关问题

  • 在C语言中,如何取得程序当前的完整路径?
  • 用C语言怎么实现改变当前路径(请看下面代码)
  • 用c语言实现无向图的最短路径的查找
  • C语言求助[戴杰斯特拉算法求图到任意点的最短路径]的原代码!!!
  • c中的路径问题。
  • 学C语言。。。
  • C语言书!
  • 如何得到C:\Program Files路径?
  • 关于C#向ACCESS存路径问题
  • c# 并非所有路径错

关键词

  • c++
  • 节点
  • 代码
  • 价值
  • 路径
  • 权值
  • dep
  • pathinfo
  • dtvalpair
  • 问题

得分解答快速导航

  • 帖主:darkwowowo
  • kbsoft
  • LLnju
  • Justin

相关链接

  • CSDN Blog
  • 技术文档
  • 代码下载
  • 第二书店
  • 读书频道

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo