Description
A network of m roads connects N cities (numbered from 1 to N). There may be more than one road connecting one city with another. Some of the roads are paid. There are two ways to pay for travel on a paid road i from city ai to city bi:
- in advance, in a city ci (which may or may not be the same as ai);
- after the travel, in the city bi.
The payment is Pi in the first case and Ri in the second case.
Write a program to find a minimal-cost route from the city 1 to the city N.
Input
The first line of the input contains the values of N and m. Each of the following m lines describes one road by specifying the values of ai, bi, ci, Pi, Ri (1 ≤ i ≤ m). Adjacent values on the same line are separated by one or more spaces. All values are integers, 1 ≤m, N ≤ 10, 0 ≤ Pi , Ri ≤ 100, Pi ≤ Ri (1 ≤ i ≤ m).
Output
The first and only line of the file must contain the minimal possible cost of a trip from the city 1 to the city N. If the trip is not possible for any reason, the line must contain the word ‘impossible’.
Sample Input
4 5 1 2 1 10 10 2 3 1 30 50 3 4 3 80 80 2 1 2 10 10 1 3 2 10 50
Sample Output
110
转载出处:http://blog.csdn.net/lyy289065406/article/details/6689310
大致题意:
有n座城市和m(1<=n,m<=10)条路。现在要从城市1到城市n。有些路是要收费的,从a城市到b城市,如果之前到过c城市,那么只要付P的钱,如果没有去过就付R的钱。求的是最少要花多少钱。
注意:路径是有向的。
解题思路:
DFS。这题当有了思路后,做起来是没有难度的,但是思维推算能力要求很高。
这题难点在于“城市与城市之间可能存在多条路径”:
1、 输入数据时可能会出现多条 从城市a到城市b的路径信息,但是费用有所差别;
2、 对于 从城市a到城市b 的同一条路径,允许重复走。
有人会问,重复走同一条路径有什么意义?单纯增加费用而已,为什么不能标记所有路径,每条路只允许走一次,这样费用不是更少么?
我开始也是陷入了这种思维,但是这种想法其实“对一半,错一半”。
先来看一组数据:
6 5
1 2 1 10 10
2 3 4 10 100
2 4 2 15 15
4 1 1 12 12
3 6 6 10 10
如果每条路只允许走一次,那么方案只有1个:
1à2à3à6 共135元
但这组数据的正确答案是67元。为什么?正确的方案如下:
1à2à4à1à2à3à6 共67元
显然1à2重复走了一次,目的是为了先到达城市4,从而使得2à3这段路的费用从100缩减到10元。
看到这里很多同学好像就恍然大悟,但是问题马上又来了。如果同一条路允许重复走,那么就不能标记了,但一旦不标记,失去了搜索的限制条件,DFS就无法结束,不是陷入死循环了?
我刚才说这种思路“对一半,错一半”,“对”是对在“重复走会增加费用”,“错”是错在“重复走的对象不是某一条路,而是某一个环路”。在同一个环路重复走才会真正增加费用。但是标记环路是很麻烦的,那么能不能根据某一条路或某一个城市重复走过的次数来判断当前所走的方案已经出现了环路? 答案是可以的。
上述的例子已经验证过了,同一条路可以重复走,但是不能无限重复走,重复的次数是有限的。那么应该重复多少次才合理?这与m值有关。题目的m值范围为<=10,那么当人一个城市被到达的次数若 >3次(不包括3),所走的方案必然出现了环路(网上的同学称之为“闸数”)。

1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 using namespace std; 5 int N,m; 6 struct node 7 { 8 int a,b; 9 int ci,pi,ri; 10 }map[20]; 11 int minS; 12 int flag[11]; 13 void dfs(int pos,int res) 14 { 15 if(pos==N) 16 { 17 if(res<minS) 18 { 19 minS=res; 20 } 21 return; 22 } 23 int i; 24 for(i=1;i<=m;i++) 25 { 26 if(pos==map[i].a && flag[map[i].b]<=3) 27 { 28 int b=map[i].b; 29 flag[b]++; 30 31 if(flag[map[i].ci]) 32 { 33 dfs(b,res+map[i].pi); 34 } 35 else 36 { 37 dfs(b,res+map[i].ri); 38 } 39 flag[b]--; 40 } 41 } 42 return; 43 } 44 int main() 45 { 46 while(~scanf("%d%d",&N,&m)) 47 { 48 int i; 49 for(i=1;i<=m;i++) 50 { 51 int a,b,c,d,e; 52 scanf("%d%d%d%d%d",&a,&b,&c,&d,&e); 53 map[i].a=a; 54 map[i].b=b; 55 map[i].ci=c; 56 map[i].pi=d; 57 map[i].ri=e; 58 } 59 minS=0xfffffff; 60 memset(flag,0,sizeof(flag)); 61 flag[1]=1; 62 dfs(1,0); 63 if(minS==0xfffffff) 64 { 65 printf("impossible\n"); 66 } 67 else 68 { 69 printf("%d\n",minS); 70 } 71 } 72 return 0; 73 }