数模论坛

 找回密码
 注-册-帐-号
搜索
热搜: 活动 交友 discuz
查看: 8099|回复: 18

[原创]参赛者必进

[复制链接]
发表于 2003-8-3 19:21:23 | 显示全部楼层 |阅读模式
我希望大家把自己对今年的比赛的一些看法说一下,
比如对某一个问题我们应该用什么方法解
发表于 2003-8-5 23:20:53 | 显示全部楼层
你们好强呀
发表于 2003-8-5 23:22:19 | 显示全部楼层
你们平时都看什么书呀,
发表于 2003-8-5 23:31:06 | 显示全部楼层
以下是引用dcyu在2003-8-4 12:04:01的发言:
Dijkstra算法哪用的着这么多代码啊??
真是faint!
30行就可以搞定了。

30行啊?有没有现成的代码可以看看的?
发表于 2003-8-3 20:00:36 | 显示全部楼层
我现在想知道94年A题当中用到的Dijkstra算法的MATLAB实现的程序,用C或C++写的也可以,请知道的大侠告诉我一下,谢谢!
发表于 2003-8-4 03:22:39 | 显示全部楼层
全是假的?
 楼主| 发表于 2003-8-4 03:58:16 | 显示全部楼层
什么都是假的
发表于 2003-8-4 15:40:55 | 显示全部楼层
以下的c++程序是在数据结构课上做的Dijkstra的算法
你要是可以看明白在修改一点(其实就是向程序里加那题的数据)就可以直接用了
导出的数据存在e:\out.txt里(这个你可以根据你自己的喜好再改)
/*
  Name: Shortest Path Used DJ
  Author: Ran Ni
  Description: Shortest Path Used DJ and the graph is saved in Crosslist.
  Date: 07-06-03 18:09
  Copyright: Ran Ni
*/
#include <iostream.h>//输入输出流头文件
#include <fstream.h>//文件流头文件
#define M 10//图的最大节点数
#define N 1000000//定义一个很大的数作为比较旗帜
struct path{
    int data;
    path *next;
    };
struct cnode{//十字链表中的存储图中边的节点
     int i,j;//节点所在的行和列,行列数组中的该数据存储节点的出度和入度
     int weight;//边的权重
     int dele;//标记的变量
     cnode *right;
     cnode *down;
     };
struct graph{//存储图的结构体
     int num;//图中的节点数
     cnode row[M];//行数组
     cnode vol[M];//列数组
     int edge;//图中边的数目
     };

ofstream out("e:\\out.txt");
void add(graph *g,int i,int j,int weight)//添加图中的边起点终点和权值分别为i,j和weight
{ cnode *p,*q;
  q=new cnode;//申请空间存储新的边
  q->i=i;
  q->j=j;
  q->weight=weight;
  q->right=NULL;//指针初始化
  q->down=NULL;
  q->dele=0;//表示该边没有被删除
  p=&(g->row);
  p->dele=0;
  g->vol.dele=1;//dele为1表示该节点没有被删除
  if(!p->right)//如果该节点所在行没有节点,直接添加
  { p->right=q;
  }else if(p->right->j>j)//如果该节点所在行的第一个已有的节点所在列比该节点大,将其添加在第一个节点之前
  { q->right=p->right;
    p->right=q;
  }else if(p->right->j==j)//如果该节点已经存在,将其覆盖
  { p->weight=q->weight;
  }else if(p->right->j<j)//如果该节点所在行的第一个已有的节点所在列比该节点小,需要寻找合适的位置添加该节点
  { while(!((p->right==NULL)||((p->j<j)&&(p->right->j>j))||(p->j==j)))//三个可能添加的位置
    { p=p->right;
    }
    if(p->right==NULL)//当应该将其添加在所在行的最后一个时
    { p->right=q;
    }
    else if((p->j<j)&&(p->right->j>j))//当应该将其添加在某两个节点之间时
    { q->right=p->right;
      p->right=q;
    }else if(p->j==j)//当该节点已经存在时
    { p->weight=q->weight;
    }
  }
  g->row.i++;//图中第i个节点的出度加1
  g->vol.i++;
  p=&(g->vol[j]);//以下为将该节点进行对列添加进行类似的操作
  p->dele=0;
  g->row[j].dele=1;
  if(!p->down)
  { p->down=q;
  }else if(p->down->i>i)
  { q->down=p->down;
    p->down=q;
  }else if(p->down->i==i)
  { p->weight=q->weight;
  }else if(p->down->i<i)
  { while(!((p->down==NULL)||((p->i<i)&&(p->down->i>i))||(p->i==i)))
    { p=p->down;
    }
    if(p->down==NULL)
    { p->down=q;
    }
    else if((p->i<i)&&(p->down->i>i))
    { q->down=p->down;
      p->down=q;
    }else if(p->i==i)
    { p->weight=q->weight;
    }
  }
  g->vol[j].j++;//图中第j个节点的入度加1
  g->row[j].j++;
  g->edge++;
}

/*
  viod change(path *,path *q,int,int)
  p,q分别指向存储start节点到q->data节点和p->data节点的最短路径的链表的头节点
  n为边的终点,data为新添加的边的权值
  本函数的作用是将q的链表深拷贝到p(首先将链表p销毁),再在p最后加一个新边data(终点为n)
*/
void change(path *p,path *q,int n,int data)
{ path *r=p;
  while(r->next)//销毁链表p
  { r=p;
    while(r->next->next)
    { r=r->next;
    }
    delete r->next;
    r->next=NULL;
  }
  r=p;
  path *t=q;
  while(t->next)//拷贝q到p
  { t=t->next;
    r->next=new path;
    r=r->next;
    r->data=t->data;
    r->next=NULL;
  }
  p->data=q->data+data;//在最后添加新边
  r->next=new path;
  r->next->data=n;
  r->next->next=NULL;
}
/*
  打印起点start到终点end的最短路径(其链表存在p中)
*/
void print(int start,int end,path *p)
{ if(p->data!=N)//如果start到end存在最短路径,打印p所指向的链表
  { cout<<"\nThe shortest distance of the"<<start<<"th"<<" node "<<"between the "<<end<<"th node is "<<p->data<<endl;
    out<<"\nThe shortest distance of the"<<start<<"th"<<" node "<<"between the "<<end<<"th node is "<<p->data<<endl;
    cout<<"The path is:"<<endl;
    out<<"The path is:"<<endl;
    while(p->next)//打印路径
    { p=p->next;
      cout<<p->data<<" ";
      out<<p->data<<" ";
    }
  }
  else//当不存在start到end的最短路径时,打印没有最短路径,即不可达
  { cout<<"\nThere is no path from the "<<start<<"th node to the "<<end<<"th node.";
    out<<"\nThere is no path from the "<<start<<"th node to the "<<end<<"th node.";
  }
}  

/*
  求图g中从start到其余各个节点的最短路径,用DJ算法.
*/
void Shortestpath_Dj(graph *g,int start)
{ path dis[g->num];//创建所有存储节点最短路径的链表的头节点(头节点存储最短路径长度,以后的节点存储路径)
  for(int i=0;i<g->num;i++)//初始化标记和长度
  { g->row.dele=0;
    g->vol.dele=0;
    dis.data=N;
    dis.next=new path;
    dis.next->next=NULL;
    dis.next->data=start;
  }
  dis[start].data=0;//初始化start节点的路径链表
  g->row[start].dele=1;
  g->vol[start].dele=1;
  cnode *p=&(g->row[start]);
  while(p->right)//寻找可以和start节点直接有关系(即有边)的节点,并标记他们
  { p=p->right;
    dis[p->j].data=p->weight;
    dis[p->j].next->next=new path;
    dis[p->j].next->next->data=p->j;
    dis[p->j].next->next->next=NULL;
    g->row[p->j].dele=1;
    g->vol[p->j].dele=1;
  }
  for(int k=0;k<g->num;k++)//循环查找图中的节点g->num次
  { for(int i=0;i<g->num;i++)//遍历图中的节点
    { p=&(g->vol);
      while(p->down)//当有边指向他时,判断指向他的节点中是否有已经被标记的
      { p=p->down;
        if(g->row[p->i].dele==1)//当存在已经标记过的节点指向他时,标记该节点
        { g->row.dele=1;
          g->vol.dele=1;
          if(dis[p->i].data+p->weight<dis.data)//如果该指向他的节点的最短路径长度加上他们之间的边的权值,则调用change函数
          { change(&(dis),&(dis[p->i]),i,p->weight);
          }
        }
      }
    }
  }
  for(int i=0;i<g->num;i++)//打印start节点到所有节点的最短路径和最短路径长度
  { if(i!=start)
    { print(start,i,&(dis));
    }
  }
}

void main()
{ graph *g=new graph;//申明一个图的指针,并对其分配空间
  int start;
  g->edge=0;
  for(int i=0;i<M;i++)//变量初始化
  { g->row.right=NULL;
    g->row.down=NULL;
    g->row.i=0;
    g->row.j=0;
    g->row.weight=0;
    g->row.dele=0;
    g->vol.right=NULL;
    g->vol.down=NULL;
    g->vol.i=0;
    g->vol.j=0;
    g->vol.weight=0;
    g->vol.dele=0;
  }
  cout<<"*******************************************************"<<endl;
  cout<<"                  Shortest Path_DJ"<<endl;
  cout<<"*******************************************************"<<endl;
  cout<<"Input the number of the node in the graph:"<<endl;
  cin>>g->num;//读入图中所拥有的节点数
step1:cout<<"Input the start node of the edge:"<<endl;
  int i;
  cin>>i;//读入边的起点
  cout<<"Input the end node of the edge:"<<endl;
  int j;
  cin>>j;//读入边的终点
  if((i>g->num-1)||(j>g->num-1))//判断是否输入出错
  { cout<<"Input error!"<<endl;
    goto step1;
  }
  cout<<"Input the weight of the edge:"<<endl;
  int weight;
  cin>>weight;//读入边权
  add(g,i,j,weight);
  out<<"("<<i<<","<<j<<","<<weight<<")"<<endl;
step2:cout<<"Is there any other edge?(y/n)"<<endl;//判断是否还有其他节点
  char c;
  cin>>c;
  if(c=='y')
  { goto step1;
  }else if((c!='y')&&(c!='n'))
  { cout<<"Input error!"<<endl;
    goto step2;
  }
step3:cout<<"Input the start node"<<endl;
  cin>>start;//读入等待计算的start节点
  if(start>g->num-1)//判断是否输入出错
  { cout<<"Input error!"<<endl;
    goto step3;
  }
  Shortestpath_Dj(g,start);//求start到图g中其他各节点的最短路径
step4:cout<<"\nWould you like to calculate another node?(y/n)"<<endl;//判断是否继续计算其他节点
  char d;
  cin>>d;
  if(d=='y')
  { goto step3;
  }else if((d!='y')&&(d!='n'))
  { cout<<"Input error!"<<endl;
    goto step4;
  }
}
         

发表于 2003-8-4 17:37:14 | 显示全部楼层
我顶
发表于 2003-8-4 20:04:01 | 显示全部楼层
Dijkstra算法哪用的着这么多代码啊??
真是faint!
30行就可以搞定了。
您需要登录后才可以回帖 登录 | 注-册-帐-号

本版积分规则

小黑屋|手机版|Archiver|数学建模网 ( 湘ICP备11011602号 )

GMT+8, 2024-5-11 18:25 , Processed in 0.058243 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表