广大暑假训练1 E题 Paid Roads(poj 3411) 解题报告
题目链接:http://poj.org/problem?id=3411
题目意思:N个city 由 m 条路连接,对于一条路(假设连接Cityia和 Cityb),如果从Citya 去 Cityb的途中,之前已经走过Cityc(可能会等于a),那么就可以交p的钱,否则之前未走过Cityc,就一定要交r 的路费啦。
注意,一个点可以被反复多次走,也就是可能构成环,虽然路走长了,但路费便宜了,这个问题要考虑到。还有就是剪枝啦:如果当前求得的路费比以前求得的答案要大,那就要回溯。
mincost 明明是全局变量,多手在main里又重新声明,搞了我1个多小时才发现 = =....
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 const int maxn = 1000 + 5; 8 int head[maxn]; 9 int point_vis[maxn]; 10 int N, m, mincost; 11 12 struct adjlist // 邻接表 13 { 14 int b, c, p, r; 15 int next; 16 }node[maxn]; 17 18 void dfs(int next, int cost) 19 { 20 if (point_vis[next] > N || cost >= mincost) // 某一点被经过的次数多于N 或者当前cost比之前求出的minsum要大就回溯 21 return; 22 if (next == N) 23 { 24 mincost = cost; 25 return; 26 } 27 for (int i = head[next]; i != -1; i = node[i].next) 28 { 29 int v = node[i].b; 30 point_vis[node[i].b]++; 31 if (point_vis[node[i].c] >= 1) // 之前这个中间点c有访问过,就可以交纳在点c的费用p 32 dfs(node[i].b, cost+node[i].p); 33 else // 之前该点木有走过,只能乖乖交 r 这个费用了 34 dfs(node[i].b, cost+node[i].r); 35 point_vis[node[i].b]--; 36 } 37 } 38 39 int main() 40 { 41 while (scanf("%d%d", &N, &m) != EOF) 42 { 43 int t1, cnt = 0; 44 memset(head, -1, sizeof(head)); 45 for (int i = 0; i < m; i++) 46 { 47 scanf("%d", &t1); 48 node[cnt].next = head[t1]; 49 scanf("%d%d%d%d", &node[cnt].b, &node[cnt].c, &node[cnt].p, &node[cnt].r); 50 head[t1] = cnt++; 51 } 52 memset(point_vis, 0, sizeof(point_vis)); 53 mincost = maxn; 54 point_vis[1]++; 55 dfs(1, 0); 56 if (mincost == maxn) 57 printf("impossible\n"); 58 else 59 printf("%d\n", mincost); 60 } 61 return 0; 62 }