- 题库 :洛谷
- 题号 :5767
- 题目 :最优乘车
- link :https://www.luogu.com.cn/problem/P5767
做法 :Floyd + 神奇思路
思路:此题可以换个思路去想,以样例为例,我们不考虑换乘的次数,设同一条线路上的任意两点间的距离为1,同时不需要换乘,这时便可以惊奇的发现从1(起点)跑到n(终点)的最短路径 - 1即为正确答案!这是为什么呢?其原因是当需要换乘时,肯定会从当前线路上走到任意一点再进行换乘,至于为什么肯定会从当前线路上走到另外一点自己去想(或者评论私信问),从而换乘的次数就便是在任意一条路径上走的次数了(走完之后肯定会去换乘,最后走的一次除外)。当然我们最后答案必须减一,其原因就是当走到最后一条(再也不会换乘了)线路时,直接走到终点是不花换成次数的,而我们却记录了一次,所以最后要减一。数据很小,用Floyd实现就行了。
本题坑点:读入很坑,需要用字符串读入,还有记得把第一行行末空格给过滤掉,否则getline或gets会把这个回车也给读了。
code:
1 #include <bits/stdc++.h> 2 #define INF 0x3f3f3f3f//很大的数 3 using namespace std; 4 int n, m, x, q[100001], f[1001][1001]; 5 string s; 6 inline void floyd()//模板 7 { 8 for(register int k = 1; k <= n; ++k) 9 { 10 for(register int i = 1; i <= n; ++i) 11 { 12 for(register int j = 1; j <= n; ++j) 13 { 14 if(i != j && i != k && j != k) 15 { 16 f[i][j] = min(f[i][j], f[i][k] + f[k][j]); 17 } 18 } 19 } 20 } 21 return; 22 } 23 int main() 24 { 25 memset(f, INF, sizeof(f)); 26 scanf("%d %d ", &m, &n);//记得 + 27 while(m--) 28 { 29 int z = 0; 30 getline(cin, s);//字符串读入 31 for(register int i = 0; i < s.length(); ++i) 32 { 33 x = 0;//记录当前答案 34 while(s[i] <= '9' && s[i] >= '0')//转换(遇到空格就退了) 35 { 36 x = x * 10 + s[i] - '0';//当前所有位都向前移一位再加上最低位(转成数字) 37 ++i;//不停的加 38 } 39 q[++z] = x;//存储 40 } 41 for(register int i = 1; i <= z; ++i) 42 { 43 f[i][i] = 0;//自己到自己是0 44 for(register int j = i + 1; j <= z; ++j) 45 { 46 f[q[i]][q[j]] = 1;//车站任何一位到除了自己以外的任何一位的距离都是1 47 } 48 } 49 } 50 floyd();//经典算法 51 if(f[1][n] == INF)//到不了 52 { 53 printf("NO");//注意一本通上的这道题是N0,但好像不影响,没有这种数据 54 } 55 else 56 { 57 printf("%d", f[1][n] - 1);//记得 - 1 58 } 59 return 0; 60 }