题目链接:http://poj.org/problem?id=3411
题目大意:
- 有n座城市和m(1<=n,m<=10)条路。现在要从城市1到城市n。
- 有些路是要收费的,从a城市到b城市,如果之前到过c城市,那么只要付P的钱,如果没有去过就付R的钱。求的是最少要花多少钱。
- 注意:路径是有向的。
-
这题难点在于“城市与城市之间可能存在多条路径”:
1、 输入数据时可能会出现多条 从城市a到城市b的路径信息,但是费用有所差别;
2、 对于 从城市a到城市b 的同一条路径,允许重复走。
- 因最多有10个城市,那么我们必须防范出现环自转的现在,显然3个城市可以出现环的现象。。那么假设走10个城市且出现了3个环,
- 那么一个城市最多被利用3次,所以vis[u]<=3;
- 在同一个环路重复走才会真正增加费用。但是标记环路是很麻烦的,那么能不能根据某一条路或某一个城市重复走过的次数来判断当前所走的方案已经出现了环路? 答案是可以的。同一条路可以重复走,但是不能无限重复走,重复的次数是有限的。那么应该重复多少次才合理?这与m值有关。题目的m值范围为<=10,那么当人一个城市被到达的次数若 >3次(不包括3),所走的方案必然出现了环路。因此只需把bool vist[] 修改为 int vist[] 进行标记,本题就能解决了。
- 代码如下
/*AC*/ #include <cstdio> #include <iostream> #include <cstring> using namespace std; struct edge{ int a, b; int c, p, r; }; const int INF = 1e9; edge a[11]; int vis[11]; int n, m; int mincost; void DFS(int from, int cost){ if(from == n && cost < mincost){ mincost = cost; return; } for(int i=1; i<=m; i++){ if(a[i].a == from && vis[a[i].b]<= 3){ vis[a[i].b]++; if(vis[a[i].c]) DFS(a[i].b, cost+a[i].p); else DFS(a[i].b, cost+a[i].r); vis[a[i].b]--; } } } int main(){ while(scanf("%d %d", &n, &m) != EOF){ for(int i=1; i<=m; i++) scanf("%d %d %d %d %d", &a[i].a, &a[i].b, &a[i].c, &a[i].p, &a[i].r); memset(vis, 0, sizeof(vis)); mincost = INF; DFS(1, 0); if(mincost == INF) puts("impossible"); else printf("%d\n", mincost); } return 0; }