什么样的深度估计函数最好?

slavik 2003-09-19 04:57:21
建立一个导游系统。城市数目至少10。城市之间有交通工具相联,一个城市可以有任意多个线路出去,它们根据时刻表运行,有相应的耗时和花费,只有在发车时间才可以搭乘相应的交通工具离开,或者等待一段时间(这个也计算在路线的耗时里),再搭乘工具离开。用户指定起始位置、起始时间、必须经过的城市、终点城市。分别求花费最少、耗时最少、限定时间内花费最少三种路线。
  这个问题会有线性解法吗?如果没有那么什么样的深度估计求得最优的解的概率最高?
...全文
74 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
slavik 2003-09-24
  • 打赏
  • 举报
回复
目前做出了一个算法,但是深度估计是用查表做的,10个城市使用搜索深度20(用人对图观察的结果,有的傻,不过很方便)
我把三个搜索合在一个函数里了,所以原来可以使用D算法的最少花费搜索会有点慢。
Node、TNode、MNode的tryNextArc、hasSucc、createSucc都被重载了
R[]用来判断关键点是否被经过,当R都是负值时,说明都被走过了。如果有更快的判断方法,不妨说出来啊!
用迭代代替递归使运行变快一些,但是代码变得混乱了。整理了一个星期才变成目前的样子,各位看看有没有办法优化结构。
Arc记录了从A城市到B城市的一条交通线路,他们被保存载矩阵里,route[i][j]是一条连接i城到j城的所有arc的链表,按花费升序排列。

Node会尝试route[i][j]之间所有的arc,然后再尝试i和j的后继的arc(s)。
MNode只尝试route[i][j]的头一个,之后和Node一样。
TNode只尝试当前时间下耗时最少的,之后和Node一样。

如果i->j已经走过一次了,那么将不再走第二次。visited[][]记录这个信息,Node会考虑这个来选择j的后继城市。


//搜索路径
LogCmd* search( SearchType mode, int S, int E, int startTime,
int maxTime, vector<int>& key ) {

const int cityNum = City::getCount();

const int MAX_DEEP = 10;//cityNum*2;

int deep = 1;

int write = 1;

writeExecutionLog( "清除所有已经访问的标记" );
clearVMark();

R[0] = -1;
writeExecutionLog( "得到关键点的列表" );
for( unsigned int i = 0; i < key.size(); i++ ) {
R[write++] = key[i];
}

writeExecutionLog( "之后的全填充-1" );
for( int i = write; i<= cityNum; i++ ) {
R[i] = -1;
}

int currT = 0, currM = 0;
int minT = INT_MAX, minM = INT_MAX;
int clock = startTime;

Node* currNode = NULL;
Node* currMinPath = NULL;

bool finished = false;

//writeExecutionLog( "处理城市链表,得到< E, R, ……, S >" );
City* start = City::getCity( S );
City* end;

if( S != E ) {
end = City::getCity( E );
} else {
end = start;
}

//City::sortCity( S, E, key );

writeExecutionLog( "确定搜索模式,选择节点类型" );
writeExecutionLog( "各种策略的不同点在于他们尝试从当前位置出发的arc的顺序" );
switch( mode ) {
case MIN_MONEY_COST:
writeExecutionLog( "最少花费搜索,创建MNode" );
currNode = new MNode( start, NULL, clock );
break;
case MIN_TIME_COST:
writeExecutionLog( "最少耗时搜索,创建TNode" );
currNode = new TNode( start, NULL, clock );
break;
case MIN_MONEY_COST_WITHIN_TIME:
writeExecutionLog( "有限时间内最少花费搜索,创建Node" );
currNode = new Node( start, NULL, clock );
minT = maxTime;
break;
}

Node* THE_ROOT = currNode;

writeExecutionLog( "搜索开始" );
while( !finished ) {

writeExecutionLog( "对currNode检测" );
writeExecutionLog( currNode->CITY->NAME );

int mCost = 0;
int tCost = 0;

while( currNode->currOut != NULL ) {
writeExecutionLog( "存在可以尝试的arc,尝试他的权值,检测是否可以有后继" );
Arc* arc = currNode->currOut;

mCost = arc->MCOST;
tCost = Arc::timeCost( arc, currNode->TIME );
currM += mCost;
currT += tCost;

if( currNode->hasSucc( currT, currM, minT, minM ) ) {
writeExecutionLog( "符合搜索条件,可以有后继" );
writeExecutionLog( currNode->currOut->NAME );
currNode->createSucc();
deep++;
break;
} else {
writeExecutionLog( "没有后继,尝试下一条arc" );
currM -= mCost;
currT -= tCost;
currNode->tryNextArc();
}
}

writeExecutionLog( "对currNode检测结束");

if( currNode->next != NULL ) {

writeExecutionLog( "退出时有后继");
currNode = currNode->next;

writeExecutionLog( "检测新节点" );
if( currNode->CITY == end ) {
writeExecutionLog( "新的节点已经到达终点end" );
if( coverAllKeyPoint() ) {
writeExecutionLog( "当前搜索的路径已经覆盖了R" );

minM = currM;
minT = currT;

Node::deletePath( currMinPath );
currMinPath = Node::colonePath( THE_ROOT );

writeExecutionLog( "没有搜索end之后的点的必要" );

if( currNode != THE_ROOT ) {
writeExecutionLog( "回溯到上一点" );
currNode = currNode->prev;

Arc* arc = currNode->currOut;

mCost = arc->MCOST;
tCost = Arc::timeCost( arc, currNode->TIME );

currT -= tCost;
currM -= mCost;

currNode->releaseSucc();
currNode->tryNextArc();
deep--;
} else {
writeExecutionLog( "当前要释放的点是起始根,搜索结束" );
finished = true;
}
} else {
writeExecutionLog( "当前路径仍然没有覆盖R,所有继续搜寻" );
}
} else {
writeExecutionLog( "当前点仍然没有到达目的地" );
}

while( deep > MAX_DEEP ) {
currNode = currNode->prev;

Arc* arc = currNode->currOut;

mCost = arc->MCOST;
tCost = Arc::timeCost( arc, currNode->TIME );

currT -= tCost;
currM -= mCost;

currNode->releaseSucc();
currNode->tryNextArc();
deep--;
}

} else {
writeExecutionLog( "当前节点无后继");
writeExecutionLog( "没有再搜索的价值,释放当前节点,进入下一次循环" );
if( currNode != THE_ROOT ) {
writeExecutionLog( "回溯到上一点" );

currNode = currNode->prev;
Arc* arc = currNode->currOut;

mCost = arc->MCOST;
tCost = Arc::timeCost( arc, currNode->TIME );

currT -= tCost;
currM -= mCost;

currNode->releaseSucc();
currNode->tryNextArc();
deep--;
} else {
writeExecutionLog( "当前要释放的点是起始根,搜索结束" );
finished = true;
}
}

}

delete THE_ROOT;

writeExecutionLog( "对currNode检测结束" );

if( currMinPath == NULL ) {
writeExecutionLog( "没有找到" );
return NULL;
}

writeExecutionLog( "输出日志" );

LogCmd* log = new CmdStart( S, startTime );
LogCmd* curr = log;

while( currMinPath != NULL ) {
Node* next = currMinPath->next;
curr->setNext( currMinPath->createLogCmd() );
while( curr->getNext() != NULL ) {
curr = curr->getNext();
}
delete currMinPath;
currMinPath = next;
}

curr->setNext( new CmdEnd( minT, minM ) );
return log;

}
zzwu 2003-09-21
  • 打赏
  • 举报
回复
可在网上查 "Lee's Router".
zzwu 2003-09-21
  • 打赏
  • 举报
回复
我想可以仿照Lee氏算法来做,虽然速度慢,但算法非常简单.
ljranby 2003-09-21
  • 打赏
  • 举报
回复
这肯定是非线性的问题,用HopfieldNN做吧
lijiuhua0721 2003-09-20
  • 打赏
  • 举报
回复
这个问题好象是很难呀!!但看来不应该是线性的呀!!

还是希望高手来做一下解答!!如果解决请楼主把答案说出来!!呵呵,收藏!!
ShallowShrimp 2003-09-20
  • 打赏
  • 举报
回复
这个问题不错,值得收藏。
ZhangYv 2003-09-20
  • 打赏
  • 举报
回复
这个问题是NP复杂度的,主要应用于多播路由选择。
这个问题难度是很大的,也不是三两句说的清的,只好自己去看论文咯。
有一个近似算法是类似于最短路径的Dijkstra算法的贪心近似算法,自己找资料咯。
slavik 2003-09-19
  • 打赏
  • 举报
回复
果然有很多相关的内容,看来好好研究可以做毕业论文了^_^
ZhangYv 2003-09-19
  • 打赏
  • 举报
回复
没有线性解法,求Steiner树。网上有不少这种论文的。

33,007

社区成员

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

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