关键路径算法

overmind 2003-10-17 07:47:06
哪位大哥可以给出关键路径算法实现的源程序。
要求能在tc3.0下实现,谢谢。
...全文
152 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
stephen85 2003-10-31
  • 打赏
  • 举报
回复
思路:
首先构造一个带权有向图,其中每条弧的权表示完成某道工序所要花的时间,然后分别求出每个顶点的最早完成时间TE[vi]和最晚完成时间TL[vi].
其中TE[vi]=max{TE[vj]+Wji},vj为vi的任一前趋顶点;TL[vi]=min{TL[vj]-Wij},vj为vi的任一后继顶点。
所有满足TE[vi]=TL[vi]的顶点便为所需要的关键顶点,加上源点与汇点便可构成一条关键路径。
skywind 2003-10-31
  • 打赏
  • 举报
回复

/////////////////////////////////////////////////////////////////////
#include <conio.h>
#include <stdlib.h>
#include <ctype.h>

char map[100][100];
int maph,mapw;

static short incx[8]={ 0, 1, 1, 1, 0, -1, -1, -1 };
static short incy[8]={ -1, -1, 0, 1, 1, 1, 0, -1 };

AstarPathFind PathFind;
int startx,starty,endx,endy;
short Judge(short x,short y,short endx,short endy)
{
short dx=abs(x-endx);
short dy=abs(y-endy);
return (dx+dy)<<3;
}
char Possible(short x,short y)
{
if (x<0||y<0||x>=mapw||y>=maph) return 0;
return (map[y][x]==' ')?1:0;
}
int readmap()
{
int i,j;
FILE *f;
if ((f=fopen("map.dat","r"))==NULL) return -1;
fscanf(f,"%d,%d\n",&mapw,&maph);
for (j=0;j<maph;j++) fgets(map[j],mapw+2,f);
fclose(f);
for (j=0;j<maph;j++) for (i=0;i<mapw;i++)
{
if (map[j][i]=='s'||map[j][i]=='S') startx=i,starty=j,map[j][i]=' ';
if (map[j][i]=='e'||map[j][i]=='E') endx=i,endy=j,map[j][i]=' ';
}
return 0;
}
#include <time.h>
#define TIMES 512
int main(void)
{
int i,j;
int x,y;
long t;
double f;
if (readmap()) { printf("no map file\n"); return -1; }
short PosXY[500];
char PosR[500];
for (j=0;j<maph;j++) {
for (i=0;i<mapw;i++) putchar(map[j][i]);
putchar('\n');
}
i=PathFind.Create(mapw,maph,Possible,Judge);
if (i) {
printf("创建失败\n");
return -1;
}
PathFind.SetCloseLimited(79*24L);
PathFind.SetDirMask(0xff);
PathFind.FindPath(startx,starty,endx,endy);
PathFind.GetPosPath(PosXY,250);
PathFind.GetDirPath(PosR,500);
getch();
for (i=0;PosXY[i*2]>=0;i++)
{
x=PosXY[i*2];
y=PosXY[i*2+1];
map[y][x]='.';
}
for (j=0;j<maph;j++) {
for (i=0;i<mapw;i++)
{
putchar(map[j][i]);
if (map[j][i]=='.') map[j][i]=' ';
}
putchar('\n');
}
printf("Any key to Testing speed, finding 512 paths...\n");
getch();
for (t=clock();t==clock(););
for (i=0,t=clock();i<TIMES;i++)
{
PathFind.FindPath(startx,starty,endx,endy);
PathFind.GetPosPath(PosXY,250);
}
t=clock()-t;
f=TIMES*CLK_TCK;
f/=t;
PathFind.Release();
printf("Time to find %d paths is %ld TCK use! freq=%f \n",TIMES,t,f);
getch();
return 0;
}

/*===============================================================================
原始算法 98.088421次每秒
算法记录一 152.760656次每妙
算法记录二 157.938983次每妙
算法记录三 179.200000次每秒
用VC优化 190.334572次每妙
地图文件:map.dat
79,24
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
o o o
o ooooooo o o
o o o oooooooooooooo o
o s o o o
oooooooooooooooooo o o
o oooooooooooooooooooooooooo oooooooo o
o oooooo o oooo o o o
o o o ooo ooo o
o oooo oooo o
o o oooooooooooooooooooooooooooooooooooooooooooooo
o oooooooooooooooooooooooo o
o o
o o
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo o
o o ooooooooooo
o o ooooooo o o
o o o o o
o ooooooooooo oooooooooo o o
o o e ooo o o
o ooooo o o o
o o oooooooooooooooooo oooooooo o
o o o
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
---------------------------------------------------------------------------------*/


skywind 2003-10-31
  • 打赏
  • 举报
回复

// 路径寻找主函数
int AstarPathFind::FindPath(short startx,short starty,short endx,short endy)
{
TAstarNode *root;
int j,ok;
short x,y;
ADWORD max=0;
short MinJudge;

if (!Node||!Modify) return -1;
ClearModified();
root=&Node[starty][startx];
root->ActualCost=0;
root->EstimateCost=JudgeCost(startx,starty,endx,endy);
root->SumCost=root->EstimateCost;
root->Father=NULL;
root->Modified=1;
Modify[ModifyPoint++]=root;
AddToOpenQueue(root);
MinPos=tile_pos(startx,starty);
MinJudge=root->EstimateCost;
TargetX=endx;
TargetY=endy;
for (ok=0;ok==0;)
{
ok=GetFromOpenQueue(); // 取出Open队列估价值最小的节点放入Close中
root=Close; // 得到刚才取出的节点
if (ok||root==NULL) { ok=-1; break; }
x=(short)tile_x(root->Pos);
y=(short)tile_y(root->Pos);
if (root->EstimateCost<MinJudge) // 找到一个估计离终点最近的点
MinJudge=root->EstimateCost, MinPos=root->Pos;
if (CloseCount>max) max=CloseCount;
if (x==endx&&y==endy) MinPos=root->Pos,ok=1; // 如果走到终点了
else {
j=1;
if (DirMask&1) j&=TryTile(x,y-1,root,0);
if (DirMask&2) j&=TryTile(x+1,y-1,root,0);
if (DirMask&4) j&=TryTile(x+1,y,root,0);
if (DirMask&8) j&=TryTile(x+1,y+1,root,0);
if (DirMask&16) j&=TryTile(x,y+1,root,0);
if (DirMask&32) j&=TryTile(x-1,y+1,root,0);
if (DirMask&64) j&=TryTile(x-1,y,root,0);
if (DirMask&128) j&=TryTile(x-1,y-1,root,0);
if (j) if (PopCloseStack()) { ok=-2; break; } // 如果不是通路则从Close中取出
}
if (OpenCount>=OpenLimited||CloseCount>=CloseLimited) ok=2;
}
if (ok<0) return -2;
return 0;
}
int AstarPathFind::GetPosPath(short *PosXY,int maxpos)
{
short x,y;
ADWORD j;
TAstarNode *p,*s;
int i;
if (maxpos>1) maxpos--;
for (p=&Node[tile_y(MinPos)][tile_x(MinPos)],s=p,j=0;p&&j<MaxSize;p=p->Father,j++)
{
x=(short)tile_x(p->Pos);
y=(short)tile_y(p->Pos);
i=(p->ActualCost<maxpos)?p->ActualCost:maxpos;
PosXY[i<<1]=x;
PosXY[(i<<1)+1]=y;
}
i=(s->ActualCost+1<maxpos)?(s->ActualCost+1):maxpos;
PosXY[i*2]=-1;
PosXY[i*2+1]=-1;
return 0;
}
int AstarPathFind::GetDirPath(char *PosDir,int maxpos)
{
static char inc2r[10]={ 7,0,1,6,8,2,5,4,3,0 };
short i,x,y,nx,ny;
ADWORD j;
TAstarNode *p,*s;
x=(short)tile_x(MinPos);
y=(short)tile_y(MinPos);
if (maxpos>1) maxpos--;
for (p=&Node[y][x],s=p,j=0;p&&j<MaxSize;p=p->Father,j++)
{
nx=(short)tile_x(p->Pos);
ny=(short)tile_y(p->Pos);
i=(p->ActualCost<maxpos)?(p->ActualCost):maxpos;
PosDir[i]=inc2r[(y-ny+1)*3+x-nx+1];
x=nx;
y=ny;
}
i=(s->ActualCost+1<maxpos)?(s->ActualCost+1):maxpos;
PosDir[i]=8;
return 0;
}
int AstarPathFind::Create(int mapw,int maph,char (*MoveCheck)(short,short),short (*JudgeFun)(short x,short y,short,short))
{
int i,j;

height=maph; width=mapw;
MaxSize=maph; MaxSize*=mapw;
Modify=new TAstarNode*[MaxSize*2];
if (!Modify) return -1;
Node=new TAstarNode*[maph];
if (!Node) { delete Modify; Modify=NULL; return -1; }
for (i=0;i<maph;i++) Node[i]=new TAstarNode[mapw];
for (i=0,j=1;i<maph;i++) if (!Node[i]) j=0;
if (!j)
{
for (i=0;i<maph;i++) if (Node[i]) delete Node[i];
delete Node;
delete Modify;
Node=NULL;
Modify=NULL;
return -2;
}
for (j=0;j<maph;j++)
for (i=0;i<mapw;i++)
{
Node[j][i].Pos=tile_pos(i,j);
Node[j][i].Modified=0;
Node[j][i].ActualCost=COST_MAX;
}
ModifyPoint=0;
SetMapCheck(MoveCheck);
SetJudgeFun(JudgeCost=JudgeFun);
SetDirMask(0x55);
SetOpenLimited(200);
SetCloseLimited(MaxSize/20);
return 0;
}
int AstarPathFind::Release()
{
int j;
if (Node) for (j=0;j<height;j++) if (Node[j]) delete Node[j];
if (Node) delete Node;
if (Modify) delete Modify;
Node=NULL;
Modify=NULL;
return 0;
}
void AstarPathFind::SetJudgeFun(short (*JudgeFun)(short,short,short,short)) { JudgeCost=JudgeFun; }
void AstarPathFind::SetMapCheck(char (*MapCheck)(short,short)) { MoveAble=MapCheck; }
void AstarPathFind::SetOpenLimited(long OL) { OpenLimited=OL; }
void AstarPathFind::SetCloseLimited(long CL) { CloseLimited=CL; }
void AstarPathFind::SetDirMask(long DM) { DirMask=(short)DM; }
skywind 2003-10-31
  • 打赏
  • 举报
回复
给你A*的代码

/*===============================================================
通用最短路径A*算法优化求解
Common shortest path finding in A*

作者 skywind 于2001年12月19日
Written by skywind On Dec.19 2001

http://www.joynb.com

*/

#ifndef _ASTAR_H_
#define _ASTAR_H_

// 从上面#ifndef开始到#endif结束是头文件内容
typedef unsigned long ADWORD;
class AstarPathFind
{
protected:
struct TAstarNode
{
ADWORD Pos; // 该点的坐标(16,16)的模式保存(y,x)
short ActualCost; // 保存从起点到该节点的实际开销
short EstimateCost; // 保存此点的估价开销
short SumCost; // 上面两者之和
TAstarNode *Father; // 此点的父节点
TAstarNode *Prev; // 在Open或者Next中的上一个节点
TAstarNode *Next; // 在Open或者Next链表中的下一个节点
char Modified; // 该节点是否被修改过,记录而备清除1空,2 Open,4 Close
short DirWalked; // 有字节点的方向(未用)
short DirFrom; // 从哪个方向来的(未用)
};
TAstarNode **Node; // 对应地图中每个节点
TAstarNode *Open; // 保存没有处理的按估计值排序的节点
TAstarNode *Close; // 保存处理过的节点
TAstarNode **Modify; // 保存修改过的节点
int height; // 地图的高度
int width; // 地图的宽度
ADWORD MaxSize; // 最大面积即height*width
ADWORD ModifyPoint; // Modify数组的指针
ADWORD OpenCount; // Open队列中的节点数目
ADWORD CloseCount; // Close队列里面的节点数目
ADWORD OpenLimited; // Open队列最多节点数目
ADWORD CloseLimited; // Close队列最多节点数目
short DirMask; // 要搜索方向的标志,0-7位为从上开始顺时针七个方向
ADWORD MinPos; // 终点或最接近终点的节点
short TargetX; // 终点坐标
short TargetY;
char (*MoveAble)(short x,short y); // 检查地图是否可以移动函数指针
short (*JudgeCost)(short,short,short,short); // 取得估计值的函数指针
char AddToOpenQueue(TAstarNode *node); // 将节点排序加入Open队列
char GetFromOpenQueue(); // 从Open队列取出最小的并放入Close队列
char PopCloseStack(); // 取出Close队列中的节点
void ClearModified(); // 清除所有搜索记录
char TryTile(short x,short y,TAstarNode *Father,char FromDir);
public:
int Create(int map_w,int map_h,char (*MoveCheck)(short x,short y),short (*JudgeFun)(short x,short y,short dx,short dy));
int Release();
virtual int FindPath(short startx,short starty,short endx,short endy);
int GetPosPath(short *PosXY,int maxpos);
int GetDirPath(char *Dirs,int maxpos);

void SetJudgeFun(short (*JudgeFun)(short,short,short,short));
void SetMapCheck(char (*MapCheck)(short,short));
void SetOpenLimited(long OpenLimited);
void SetCloseLimited(long CloseLimited);
void SetDirMask(long DirMask);
};

#endif


#include <stdio.h>

#define COST_MAX 30000
#define tile_pos(x,y) (((ADWORD)y<<16)|x)
#define tile_x(pos) (pos&0xffff)
#define tile_y(pos) (pos>>16)

// 待处理节点入队列, 依靠对目的地估价距离插入排序
char AstarPathFind::AddToOpenQueue(TAstarNode *node)
{
ADWORD i;
short f=node->SumCost;
register TAstarNode *p,*b;
node->Modified|=2; // 记录Open标志
for (b=NULL,p=Open,i=0;p&&i<=OpenCount;b=p,p=p->Next,i++)
if (f<=p->SumCost) break;
if (i>OpenCount) return -2;
node->Next=p;
node->Prev=b;
if (b) b->Next=node;
else Open=node;
if (p) p->Prev=node;
OpenCount++;
return 0;
}
// 将离目的地估计最近的方案出队列
char AstarPathFind::GetFromOpenQueue()
{
TAstarNode *BestChoice=Open;
if (!Open) return -1;
Open=Open->Next;
if (Open) Open->Prev=NULL;
if (BestChoice->Modified&4) return -2; // 已经在Close中了
BestChoice->Next=Close;
BestChoice->Prev=NULL;
BestChoice->Modified&=5; // 清除Open标志
BestChoice->Modified|=4; // 设置Close标志
if (Close) Close->Prev=BestChoice;
Close=BestChoice;
OpenCount--;
CloseCount++;
return 0;
}
// 释放栈顶节点
char AstarPathFind::PopCloseStack()
{
if (Close) {
Close->Modified&=3; // 清除Close标志
Close=Close->Next;
if (Close) Close->Prev=NULL;
CloseCount--;
return 0;
}
return -1;
}
// 还原修改过的所有节点
void AstarPathFind::ClearModified()
{
ADWORD i;
for (i=0;i<ModifyPoint;i++) {
Modify[i]->Modified=0;
Modify[i]->ActualCost=COST_MAX;
}
ModifyPoint=0;
OpenCount=0;
CloseCount=0;
Open=NULL;
Close=NULL;
}
// 尝试下一步移动到 x,y 可行否
char AstarPathFind::TryTile(short x,short y,TAstarNode *Father,char FromDir)
{
register TAstarNode *node;
short ActualCost;

if (!MoveAble(x,y)) return 1; // 如果地图无法通过则退出
node=&Node[y][x];
ActualCost=Father->ActualCost+1; // 实际值计算
if (ActualCost>=node->ActualCost) return 1;
if (node->Modified&2) // 在Open表中就清除
{
if (node->Next) node->Next->Prev=node->Prev;
if (node->Prev) node->Prev->Next=node->Next;
else Open=node->Next;
OpenCount--;
node->Modified=1;
node->Father=Father;
node->ActualCost=ActualCost;
node->SumCost=ActualCost+node->EstimateCost;
AddToOpenQueue(node);
} else if (node->Modified&4) { // 在Close表中就清除
if (node->Next) node->Next->Prev=node->Prev;
if (node->Prev) node->Prev->Next=node->Next;
else Close=node->Next;
CloseCount--;
node->Modified=1;
node->Father=Father;
node->ActualCost=ActualCost;
node->SumCost=ActualCost+node->EstimateCost;
AddToOpenQueue(node);
} else {
if (!(node->Modified&1)) Modify[ModifyPoint++]=node; // 记录这个修改过的点以还原
node->Modified=1;
node->Father=Father;
node->DirFrom=FromDir;
node->ActualCost=ActualCost;
node->EstimateCost=JudgeCost(x,y,TargetX,TargetY);
node->SumCost=ActualCost+node->EstimateCost;
AddToOpenQueue(node); // 将节点加入Open队列
}
return 0;
}
zhouqingyuan 2003-10-31
  • 打赏
  • 举报
回复
up
pxwzd123 2003-10-18
  • 打赏
  • 举报
回复
//AOE-Activity On Edge
//求关键路径

#include"stdio.h"
#define Maxnum 9
int AOEbegin(void);
main()
{
int judge;
judge=AOEbegin();
if(!judge)
printf("There is no result!");
}

int AOEbegin(void)
{
int i,j,k,flag,flag1;
int B[Maxnum][2];
int Graph[Maxnum][Maxnum];

for(i=0;i<Maxnum;i++)
for(j=0;j<Maxnum;j++)
Graph[i][j]=0;
Graph[0][1]=2;
Graph[0][2]=3;
Graph[0][3]=5;
Graph[1][4]=7;
Graph[2][5]=6;
Graph[3][5]=4;
Graph[4][6]=6;
Graph[4][7]=6;
Graph[5][7]=2;
Graph[6][8]=3;
Graph[7][8]=4;
for(i=0;i<Maxnum;i++)
for(j=0;j<2;j++)
B[i][j]=0;

for(k=0;k<Maxnum;k++)
{
flag1=0;
for(i=0;i<Maxnum;i++)
{
flag=0;
for(j=0;j<Maxnum;j++)
{
if((Graph[j][i])&&(Graph[j][i]<99))
{
flag=1;break;
}
}
if(!flag)//找到入度为0的点
{
flag1=1;
for(j=0;j<Maxnum;j++)
{
if(Graph[j][i]>=100)//即顶点有到达当前顶点的边
{
if(B[i][0]==0)
{B[i][0]=Graph[j][i]/100+B[j][0];B[i][1]=j+1;}
if(B[i][0]>(Graph[j][i]/100+B[j][0]))
{B[i][0]=Graph[j][i]/100+B[j][0];B[i][1]=j+1;}
}
}
for(j=0;j<Maxnum;j++)//求出该点最短时间后的处理
{
if((!Graph[i][j])||(Graph[i][j]==99))
Graph[i][j]=99;
else
Graph[i][j]*=100;
Graph[j][i]=99;
}
}
}
if(!flag1)
return 0;
}
for(i=0;i<Maxnum;i++)
printf("The point %d's last time is:%d\n",i+1,B[i][0]);
i=Maxnum-1;
do
{
printf(" < %d",B[i][1]);
i=B[i][1];
}while(B[i][1]!=1);
printf(" <1\n");

return 1;
}
kotton8848 2003-10-18
  • 打赏
  • 举报
回复
帮你顶。。

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧