DFS之北大百炼1724
原创
©著作权归作者所有:来自51CTO博客作者说文科技的原创作品,请联系作者获取转载授权,否则将追究法律责任
DFS专题之北大百炼1724
- 先给出源码
//AC
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int K,N,R;
//面向对象的思想 --> 将路的信息抽象为一个结构体,然后存储
struct Road {
int d,L,t;// destination length toll
};
vector<Road> cityMap[110]; //邻接表。cityMap[i]是从点i有路连到的城市集合
int minLen = 1 << 30; //当前找到的最优路径的长度
int totalLen; //正在走的路径的长度
int totalCost ; //正在走的路径的花销
int visited[110]; //城市是否已经走过的标记
int minL[110][10100]; //minL[i][j]表示从1到i点的,花销为j的最短路的长度
void Dfs(int s) //从 s开始向N行走
{
if( s == N )//如果到达N
{
minLen = min(minLen,totalLen);//求最短路径
return ;
}
for( int i = 0 ;i < cityMap[s].size(); ++i ){//遍历所有连通节点
int d = cityMap[s][i].d; //s 有路连到d
if(! visited[d] ) {//若d未被访问
int cost = totalCost + cityMap[s][i].t; //记住 cityMap[s][i]存储的是Road
if( cost > K)
continue;//这里并不是return!!!
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;
Dfs(d);
//下面是回溯的过程!!! ----> 上面的节点d已经走过,但是仍然不能保证后面的路径计算过程中
//用不到节点d,所以一定要给节点d回溯!!这是本题的关键。
visited[d] = 0;
totalCost -= cityMap[s][i].t;
totalLen -= cityMap[s][i].L;
}
}
}
int main()
{
cin >>K >> N >> R;//最多钱 城市数 路数
for( int i = 0;i < R; ++ i){
int s; // 一条路的始发点
Road r; //结构体r 代表一条路 Road
cin >> s >> r.d >> r.L >> r.t;
if( s != r.d ) //如果始发点和到达点不是同一城市 --- 添加到cityMap中
cityMap[s].push_back(r);
}
for( int i = 0;i < 110; ++i )
{
for( int j = 0; j < 10100; ++ j )
minL[i][j] = 1 << 30;
}
memset(visited,0,sizeof(visited));
totalLen = 0;
totalCost = 0;
visited[1] = 1;
minLen = 1 << 30;
Dfs(1);
if( minLen < (1 << 30))
cout << minLen << endl;
else
cout << "-1" << endl;
}
/*
5
6
7
1 2 2 3
2 4 3 3
3 4 2 4
1 3 4 1
4 6 2 1
3 5 2 0
5 4 3 2
**/
- 需要解决的问题