题目来源:https://vjudge.net/problem/POJ-1724
分析:从城市1开始深度优先遍历整个图,找到所有能走到N的走法,选一个最优的。如果当前已找到最优路径走法为L,那么在继续搜索的过程中,总长度大于L,则放弃该条路。minL[i][j]表示走到i时花费j的最短长度,如果走到i时总花费大于min[i][j],则不必走下去了。
代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include <sstream>
#include <vector>
using namespace std;
struct node{
int d,l,t;
//d为目的地城市 l为道路的长度 t是收费
};
vector<vector<node> > cityMap(110);
int minRoad = 1<<30; //最短路径
int totalRoad; //当前走的路径
int totalCost; //当前花费
int visited[110]; //判断是否经过该点
int minL[110][10010]; //minL[i][j]表示从1到i点,花销为j的最短路径
int K,N,R;
//k为花费的最大硬币数目 N为城市的总数 R为道路的总数
void dfs(int k){
if(k == N){
minRoad = min(minRoad,totalRoad);
return;
}
for(int i = 0;i<cityMap[k].size();++i){
if(!visited[cityMap[k][i].d]){
int cost = totalCost + cityMap[k][i].t;
if(cost>K){
continue;
}
if(totalRoad+cityMap[k][i].l >= minRoad || totalRoad+cityMap[k][i].l>=minL[cityMap[k][i].d][cost]){
continue;
}
totalRoad += cityMap[k][i].l;
totalCost += cityMap[k][i].t;
minL[cityMap[k][i].d][cost] = totalRoad;
visited[k] = 1;
dfs(cityMap[k][i].d);
visited[cityMap[k][i].d] = 0;
totalRoad -= cityMap[k][i].l;
totalCost -= cityMap[k][i].t;
}
}
}
int main(){
cin >> K >> N >> R;
for(int i = 0;i<R;++i){
int begin;
node s;
cin >> begin >> s.d >> s.l >> s.t;
if(begin != s.d){
cityMap[begin].push_back(s);
}
}
totalRoad = 0;
totalCost = 0;
memset(visited,0,sizeof(visited));
for(int i = 0;i<110;++i){
for(int j = 0;j<10010;++j){
minL[i][j] = 1<<30;
}
}
visited[1] = 1;
dfs(1);
if(minRoad < (1<<30)){
cout << minRoad << endl;
}
else{
cout << "-1" << endl;
}
return 0;
}