【Optimal Path】Lift.cpp 奇怪的电梯
来源:互联网 发布:山东邦和康欣淘宝网 编辑:程序博客网 时间:2024/05/21 06:56
问题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。
样例
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;}
好了 最短路径告一段落
- 【Optimal Path】Lift.cpp 奇怪的电梯
- HDU1548 A strange lift 奇怪的电梯(BFS+队列)
- 奇怪的电梯
- 奇怪的电梯 bfs
- 奇怪的电梯
- 奇怪的电梯
- 奇怪的电梯
- 奇怪的电梯
- 奇怪的电梯
- 奇怪的电梯
- 奇怪的电梯
- 奇怪的电梯
- P1135 奇怪的电梯
- 电梯(lift)
- 【其他】【RQNOJ】奇怪的电梯
- 【最短路】奇怪的电梯
- 【洛谷 1135】 奇怪的电梯
- 洛谷 P1135 奇怪的电梯
- APK安装过程及原理详解
- Unix/Linux 中的 shell 机制
- 常用CMOS模拟开关功能和原理(4066,4051-53)
- java泛型类的使用
- Visual Assist X 10.6.1845官网下载(含破解注册补丁)
- 【Optimal Path】Lift.cpp 奇怪的电梯
- 期中测验题目及参考答案 类-对象-运算符重载
- 实验九:随机生成10个不同的数
- NAO机器人零部件旋转角度以及名称汇总
- 菲波那契数的迭代计数
- Android OpenGL详解一
- CodeForces Round #119 (187B) - AlgoRace
- 太空鸟瞰沙特阿拉伯沙漠农业区
- 使用SharePoint2010模式对话框(转)