奇怪的电梯
题目链接 https://www.luogu.com.cn/problem/P1135
奉上bfs和dfs两种方法。
bfs:在本题中,相邻状态为当前所在楼层通过按向上或向下按钮所能到达的楼层,每个状态要记录的信息包括楼层编号和按按钮的次数。
先判断是否到达终点,是则返回x.step(到达此楼层一共需要按钮的次数),再判断下一个到达的楼层是否越界或是否已经被标记过。
放AC代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a,b,ans=0; 4 int k[210]; 5 int vis[210];//标记数组 6 struct node 7 { 8 int id;//表示楼层号 9 int step;//表示按钮次数 10 }x; 11 int bfs(int a) 12 { 13 vis[a]=1; 14 queue<node>q; 15 q.push((node){a,0});//起始点入队 16 while(!q.empty()) 17 { 18 x=q.front(); 19 q.pop(); 20 if(x.id==b) return x.step; 21 if(x.id+k[x.id]<=n&&!vis[x.id+k[x.id]]) 22 { 23 q.push((node){x.id+k[x.id],x.step+1}); 24 vis[x.id+k[x.id]]=1; 25 } 26 if(x.id-k[x.id]>=1&&!vis[x.id-k[x.id]]) 27 { 28 q.push((node){x.id-k[x.id],x.step+1}); 29 vis[x.id-k[x.id]]=1; 30 } 31 } 32 return -1; 33 } 34 int main() 35 { 36 ios::sync_with_stdio(false); 37 cin>>n>>a>>b; 38 for(int i=1;i<=n;i++) 39 cin>>k[i]; 40 cout<<bfs(a); 41 return 0; 42 }
dfs:利用剪枝的思想,若到达终点后,将sum赋给ans,继续搜索,直到sum继续增大超过最优结果ans,则return,这样有最优结果ans依然没有被改变,所以判断是否到达终点(第8行)和剪枝(第9行)语句可以互换位置,结果相同。
放AC代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a,b,ans=0xffffff;//即INT_MAX 4 int vis[210]; 5 int k[210]; 6 void dfs(int now,int sum) 7 { 8 if(now==b) ans=min(ans,sum); 9 if(sum>ans) return;//剪枝 10 vis[now]=1;//标记已走 11 //不越界就搜 12 if(now+k[now]<=n&&!vis[now+k[now]]) dfs(now+k[now],sum+1); 13 if(now-k[now]>=1&&!vis[now-k[now]]) dfs(now-k[now],sum+1); 14 vis[now]=0;//回溯 15 } 16 int main() 17 { 18 cin>>n>>a>>b; 19 for(int i=1;i<=n;i++) 20 { 21 cin>>k[i]; 22 } 23 vis[a]=1; 24 dfs(a,0); 25 if(ans!=0xffffff) cout<<ans; 26 else cout<<-1; 27 return 0; 28 }