【Optimal Path】Lift.cpp 奇怪的电梯
2012-05-14 20:33
232 查看
问题2: 奇怪的电梯
( lift.pas )
要求:此题用floyd和dijstra算法分别完成。
问题描述:
呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?
输入格式:lift.in
输入文件共有二行,第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N),第二行为N个用空格隔开的正整数,表示Ki。
输出格式:lift.out
输出文件仅一行,即最少按键次数,若无法到达,则输出-1。
样例
然后第二种方法 Dijkstra 还是先建图 每次选一个离dist最小的点加入路径中 再更新其他点的dist值
最后输出Dist[B] 注意dist[i]的初值是Map[A][i]
代码如下
那么 下面是最常用也是最好记的方法 笔者极力推荐的 SPFA 关于这个算法的背景笔者就不多介绍了
SPFA 在形式上和宽度优先搜索非常类似
不同的是宽度优先搜索中一个点出了队列就不可能重新进入队列
但是SPFA中一个点可能在出队列之后再次被放入队列,也就是一个点改进过其它的点之后,过了一段时间可能本身被改进,于是再次用来改进其它的点
这样反复迭代下去
………………就出答案了
SPFA很快……
好了 最短路径告一段落
( lift.pas )
要求:此题用floyd和dijstra算法分别完成。
问题描述:
呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?
输入格式:lift.in
输入文件共有二行,第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N),第二行为N个用空格隔开的正整数,表示Ki。
输出格式:lift.out
输出文件仅一行,即最少按键次数,若无法到达,则输出-1。
样例
lift.in | lift.out |
5 1 5 3 3 1 2 5 | 3 |
#include <cstdio> #include <iomanip> #include <cstdlib> #include <cstring> #define min(a, b) (a < b ? a : b) #define fi "lift.in" #define fo "lift.out" namespace Solve { int N; int A; int B; int F[200][200]; void Init_file(); void Read_data(); void Work(); void solve(); } void Solve::Init_file() { freopen(fi, "r", stdin); freopen(fo, "w", stdout); } void Solve::Read_data() { scanf("%d%d%d", &N, &A, &B); for(int i = 0; i < N; i++) { for(int j = 0; j < N; j++) F[i][j] = 100000; F[i][i] = 0; } for(int i = 0; i < N; i++) { int x; scanf("%d", &x); if (i + x < N) F[i][i + x] = 1; if (i - x >= 0) F[i][i - x] = 1; } } void Solve::Work() { for(int k = 0; k < N; k++) for(int i = 0; i < N; i++) if(i != k) for(int j = 0; j < N; j++) if (k != j && i != j) { F[i][j] = min(F[i][j], F[i][k] + F[k][j]); } if (F[A - 1][B - 1] == 100000) printf("%d", -1); else printf("%d", F[A - 1][B - 1]); } void Solve::solve() { Init_file(); Read_data(); Work(); } int main() { Solve::solve(); return 0; }
然后第二种方法 Dijkstra 还是先建图 每次选一个离dist最小的点加入路径中 再更新其他点的dist值
最后输出Dist[B] 注意dist[i]的初值是Map[A][i]
代码如下
#include <cstdio> #include <iomanip> #include <cstdlib> #include <cstring> #define MAX 1000000 #define fi "lift.in" #define fo "lift.out" namespace Solve { int N; int A; int B; int Min; int k; int dist[500]; bool Vst[500]; int Map[200][200]; void Init_file(); void Read_data(); void Work(); void solve(); } void Solve::Init_file() { freopen(fi, "r", stdin); freopen(fo, "w", stdout); } void Solve::Read_data() { scanf("%d%d%d", &N, &A, &B); for(int i = 1; i <= N; i++) { for(int j = 1; j <= N; j++) Map[i][j] = MAX; Map[i][i] = 0; } for(int i = 1; i <= N; i++) { int x; scanf("%d", &x); if (x == 0) continue; if (i + x <= N) Map[i][i + x] = 1; if (i - x >= 1) Map[i][i - x] = 1; } } void Solve::Work() { for(int i = 1; i <= N; i++) { dist[i] = Map[A][i]; } Vst[A] = 1; for(int i = 1; i <= N - 1; i++) //共标记 N - 1 个点 { //找一个dist最小未被标记的节点K int k; Min = MAX; for(int j = 1; j <= N; j++) { if (!Vst[j] && Min > dist[j]) { Min = dist[j]; k = j; } } if (k == 0) return; Vst[k] = 1; for(int j = 1; j <= N; j++) { if (!Vst[j] && dist[j] > dist[k] + Map[k][j]) dist[j] = Map[k][j] + dist[k]; } } if (dist[B] == MAX) printf("%d", -1); else printf("%d", dist[B]); } void Solve::solve() { Init_file(); Read_data(); Work(); } int main() { Solve::solve(); return 0; }
那么 下面是最常用也是最好记的方法 笔者极力推荐的 SPFA 关于这个算法的背景笔者就不多介绍了
SPFA 在形式上和宽度优先搜索非常类似
不同的是宽度优先搜索中一个点出了队列就不可能重新进入队列
但是SPFA中一个点可能在出队列之后再次被放入队列,也就是一个点改进过其它的点之后,过了一段时间可能本身被改进,于是再次用来改进其它的点
这样反复迭代下去
………………就出答案了
SPFA很快……
#include <cstdio> #include <iomanip> #include <cstdlib> #include <cstring> #define min(a, b) (a < b ? a : b) #define fi "lift.in" #define fo "lift.out" namespace Solve { int N; int A; int B; int L; int R; int Map[500][500]; bool Vst[500]; int dist[500]; int queue[500]; int Father[500]; void Init_file(); void Read_data(); void Work(); void solve(); } void Solve::Init_file() { freopen(fi, "r", stdin); freopen(fo, "w", stdout); } void Solve::Read_data() { scanf("%d%d%d", &N, &A, &B); for(int i = 0; i < N; i++) { for(int j = 0; j < N; j++) Map[i][j] = 987654321; Map[i][i] = 0; } for(int i = 0; i < N; i++) { int x; scanf("%d", &x); if (x == 0) continue; if (i + x < N) Map[i][i + x] = 1; if (i - x >= 0) Map[i][i - x] = 1; } } void Solve::Work() { // memset(dist, 0x3f, sizeof(dist)); for(int i = 0; i < N; i++) { dist[i] = 98765432; } L = R = 0; dist[A - 1] = 0; queue[R] = A - 1; Vst[A - 1] = 1; // printf("%d ", queue[0]); while(L <= R) { int now = queue[L]; // printf("%d ", now); Vst[now] = 0; for(int j = 0; j < N; j++) { if(Map[now][j]) { if (dist[j] > dist[now] + Map[now][j]) { dist[j] = dist[now] + Map[now][j]; Father[j] = now; if (!Vst[j]) { queue[++R] = j; Vst[j] = 1; } } } } L++; } if (dist[B - 1] != 98765432) printf("%d", dist[B - 1]); else printf("%d", -1); } void Solve::solve() { Init_file(); Read_data(); Work(); } int main() { Solve::solve(); return 0; }
好了 最短路径告一段落
相关文章推荐
- HDU 1548 A strange lift 奇怪的电梯(BFS,水)
- 洛谷P1135 奇怪的电梯
- CSUST 第九届校赛I-奇怪的电梯(DFS)
- 洛谷 P1135 奇怪的电梯
- ACM-奇怪的电梯(广度优先搜索、AC)
- 奇怪的strcore.cpp内存泄露
- 奇怪的电梯
- 奇怪的电梯-弗洛伊德算法介绍
- [洛谷1135]奇怪的电梯
- 练习赛12.2.奇怪电梯
- 洛谷 奇怪的电梯 STL 版队列
- hdu1584 A strange lift (电梯最短路径问题)
- 石油大oj 1825奇怪的电梯 bfs
- 洛谷 P1135 奇怪的电梯 (dfs)
- P1135 奇怪的电梯
- jzoj 1365. 【队列练习】奇怪的电梯
- 奇怪的电梯
- luogu[1135]奇怪的电梯
- 洛谷 P1135 奇怪的电梯
- 奇怪的电梯