DFS之剪枝-寻路问题

对应题目

在这里插入图片描述

最优性剪枝:

1.如果当前已经找到的最优路径程度为L,那么在继续搜索的过程中,总长度已经大于等于L的走法就可以直接放弃,不用走到底了。
保存中间值的最优性剪枝。

2.用mid[k][m]表示:走到城市k时总过路费为m的条件下,最优路径的长度。若在后续的搜索中,再次走到k时,如果总路费恰好为m,且此时的最优长度已经超过mid[k][m],则不必再走下去了。

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int K,N,R;
struct Road
{
    
    
    int d,L,t;
};
vector<vector<Road> > cityMap(110); //邻接表citymap是i点有路的集合
int minLen=1<<30;   //当前最优路径
int totalLen=0;     //当前路径长度
int totalCost=0;   //当前路径花销
int visited[110];  //标记是否已经走过
int minL[110][10100];    //从1到i点花销为j的最短长度
void Dfs(int s)      
{
    
    //从s开始向N行走
    if(s==N)
    {
    
    //如果到达终点,返回当前总路径和最短路径。
       minLen = min(minLen,totalLen);
       return ;
     }
     for(int i=0;i<cityMap[s].size();++i )
     {
    
    //遍历cityMap的所有元素
         int d=cityMap[s][i].d; 
         //s有路连到d
         if(! visited[d] )
         {
    
    //确定d城市没有走过
              int cost=totalCost+cityMap[s][i].t;
              //计算当前花销
              if(cost>K) continue;		//可行性剪枝
              //如果花销大于总金额,直接跳过。
              if(totalLen+cityMap[s][i].L>=minLen||totalLen+cityMap[s][i].L>=minL[d][cost]) continue;
              //如果当前总路径>=之前走过该城市时的路径,直接跳过。
              totalLen+=cityMap[s][i].L;
              totalCost+=cityMap[s][i].t;
              minL[d][cost] = totalLen;
              visited[d] = 1;
              //累加所有的数据并标价城市为1
              Dfs(d);
              //从当前位置出发往N走
              visited[d]=0;
              totalCost-=cityMap[s][i].t;
              totalLen-=cityMap[s][i].L;
              //如果不能到达N或者条件不允许,退回。
        }
    }
}

int main()
{
    
    
    cin >>K >> N >> R;
    //读入K(鲍勃所有的钱),N(城市的总数量),R(道路的总数量)
    for( int i = 0;i < R; ++ i)
    {
    
    
      int s;
      //城市的序号
      Road r;
      //Road类型的变量r
      cin >> s >> r.d >> r.L >> r.t;
      //读入出发城市的序号、目的城市的序号、道长和过路费。
      if( s != r.d )
      //排除只有一个城市的情况
      cityMap[s].push_back(r);
      //将r添加到cityMap中
    }
    for( int i = 0;i < 110; ++i )
      for( int j = 0; j < 10100; ++ j )
         minL[i][j] = 1 << 30;
     memset(visited,0,sizeof(visited));
     //先将所有的城市都标记为0
     visited[1] = 1;
     //然后把第一个城市标记为1
     Dfs(1);
     //调用深度搜索函数
     if( minLen < (1 << 30))
     //如果有比极大值小的路径则输出
     cout << minLen << endl;
     else
     //如果没有则输出-1
     cout << "-1" << endl;
}

猜你喜欢

转载自blog.csdn.net/wuyvle/article/details/113558978