对应题目
最优性剪枝:
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;
}