题很简单,但是需要些剪枝技巧,我的做法是,先不管Pi,直接用dijkstra,求得1到N的最短距离,作为搜索上界或次优解,再用深搜,对边搜索,求得最优解,刚开始没有求上界的时候TLE,加了以后0ms AC。看来剪枝很重要。
代码
1 /*搜索 + 剪枝,有的边可能经过两次*/
2 #include<stdio.h>
3 #include<string.h>
4 #define INF 1000
5 #define NN 12
6 int N, m, ans;
7 int a[12], b[12], c[12], p[12], r[12];
8 int vis[12];
9
10 char mark[NN];
11 int map[NN][NN];
12 int dis[NN];
13 void dijkstra(int t) // t表示源点
14 {
15 int i, j, min, key, num;
16 for (i = 1; i <= N; i++)
17 dis[i] = map[t][i];
18 mark[t] = 1;
19 num = N - 1;
20 while (num--)
21 {
22 min = INF + 1;// 容易出错
23 key = 0;
24 for (i = 1; i <= N; i++)
25 if (!mark[i] && dis[i] < min)
26 {
27 min = dis[i];
28 key = i;
29 }
30 mark[key] = 1;
31 for (j = 1; j <= N; j++)
32 if (!mark[j] && dis[key] + map[key][j] < dis[j])
33 dis[j] = dis[key] + map[key][j];
34 }
35 }
36
37
38 void dfs(int cur, int sum){
39 // printf("%d %d\n", cur, sum);
40 if (sum >= ans) return;
41 if (cur == N){
42 ans = sum;
43 return;
44 }
45
46 int i;
47 for (i = 1; i <= m; i++){
48 if (a[i] == cur){
49 vis[b[i]] += 1;
50 if (vis[c[i]] && p[i] < r[i]){
51 dfs(b[i], sum + p[i]);
52 }else{
53 dfs(b[i], sum + r[i]);
54 }
55 vis[b[i]] -= 1;
56 }
57 }
58 }
59 int main()
60 {
61 int i, j;
62 scanf("%d%d", &N, &m);
63 for (i = 1; i <= N; i++){
64 for (j = 1; j <= N; j++){
65 if (i == j) map[i][j] = 0;
66 else map[i][j] = INF;
67 }
68 }
69 for (i = 1; i <= m; i++){
70 scanf("%d%d%d%d%d", &a[i], &b[i], &c[i], &p[i], &r[i]);
71 if (r[i] < map[a[i]][b[i]]) map[a[i]][b[i]] = r[i];
72 }
73 dijkstra(1);
74 if (dis[N] == INF){
75 puts("impossible");
76 return 0;
77 }
78 memset(vis, 0, sizeof(vis));
79 vis[1] = 1;
80 ans = dis[N];
81 dfs(1, 0);
82 printf("%d\n", ans);
83 return 0;
84 }
85 /*
86 6 5
87 1 2 1 10 10
88 2 3 4 10 100
89 2 4 2 15 15
90 4 1 1 12 12
91 3 6 6 10 10
92
93 ans: 67*/
94