问题
输入
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
输出
11
解题思路
从城市1开始深度优先遍历整个图,找到所有能过到达N的走法,选一个最优的
优化:
1)如果当前已经找到的最优路径长度为L,那么在继续搜索的过程中,总长度已经大于L的走法,就可以直接放弃,不用走到底了
2)用midL[k][m]表示:走到城市k时总过路费为m的条件下,最优路径的长度。若在后续搜索中,再次走到k时,如果总路费恰好为m,且此时的路径长度已经超过midL[k][m],则不必再走下去了
代码如下
public class Main {
static int K,N,R;
static class Rode{
int d,l,t;
}
static ArrayList<Rode> list[] = new ArrayList[110];
static int minLen = Integer.MAX_VALUE; //当前找到的最优路径的长度
static int totalLen; //正在走的路径的长度
static int totalCost; //正在走的路径的花销
static int[]visited = new int[110]; //城市是否被走过
static int[][]minL = new int[110][10100];//minL[i][j],从1到i点的,花销为j的最短路的长度
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
K = in.nextInt();
N = in.nextInt();
R = in.nextInt();
for(int i=0;i<R;i++) {
int s = in.nextInt();
Rode r = new Rode();
r.d = in.nextInt();
r.l = in.nextInt();
r.t = in.nextInt();
if(s!=r.d) {
list[s] = new ArrayList<>();list[s].add(r);
}
}
for(int i=0;i<110;i++)
Arrays.fill(minL[i], Integer.MAX_VALUE);
totalLen = 0;
totalCost = 0;
visited[1] = 1;
Dfs(1);
if(minLen<Integer.MAX_VALUE)System.out.println(minLen);
else System.out.println(-1);
in.close();
}
private static void Dfs(int s) {//从s开始向n行走
if(s==N) {
minLen = Math.min(minLen, totalLen);
return;
}
for(int i=0;i<list[s].size();i++) {
int d = list[s].get(i).d;
if(visited[d]==0) {
int cost = totalCost+list[s].get(i).t;
if(cost>K)continue;
if((totalLen+list[s].get(i).l)>=minLen || totalLen+list[s].get(i).l>=minL[d][cost])
continue;
totalLen += list[s].get(i).l;
totalCost += list[s].get(i).t;
minL[d][cost] = totalLen;
visited[d] = 1;
Dfs(d);
visited[d] = 0;
totalLen -= list[s].get(i).l;
totalCost -= list[s].get(i).t;
}
}
}
}