洛谷P1135奇怪的電梯(正向暴力遞迴+剪枝優化)
阿新 • • 發佈:2018-11-09
題目連結:https://www.luogu.org/problemnew/show/P1135
題目意思很明顯,有很多種情況,找到最的方法,也就是最短路。
看了各種大佬題解,有dfs,bfs搜尋做法,floyd,djkstra最短路做法,%%%,這裡就只寫蒟蒻的深搜做法。。。
1.MLE,M8個點死迴圈空間棧超限;沒有對走過的點標記,導致還能走回去死迴圈
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <iomanip> 5#include <cstdio> 6 #include <cstring> 7 #include <cmath> 8 using namespace std; 9 typedef long long ll; 10 typedef unsigned long long ull; 11 const int maxn=1005; 12 int a[maxn]; 13 int vis[maxn][maxn]; 14 int N,A,B; 15 int ans=1e9; 16 int p=1; 17 18 void so(int last,int step)19 { 20 //p++; 21 //if(p>1e4) return; 22 if(last==B) 23 { 24 if(ans>step) ans=step; 25 return; 26 } 27 28 int s=last+a[last],x=last-a[last]; 29 if(s<=N) so(s,step+1); 30 if(x>=1) so(x,step+1); 31 } 32 33 int main() 34 { 35 ios::sync_with_stdio(false); cin.tie(0); 36 37 cin>>N>>A>>B; 38 for(int i=1;i<=N;i++) cin>>a[i]; 39 40 so(A,0); 41 42 if(ans==1e9) cout<<"-1"<<endl; 43 else cout<<ans<<endl; 44 45 return 0; 46 }
2.TLE,標記了但T2個點可以走的路數太多,一條一條走時間太多;
幾乎每條路都是通的,這樣更新回來還要重走!
我試了下最後2點資料,真是跑了好長好長時間才出來答案。。。
這就對dfs深搜很不利了,這種情況可以考慮剪枝或記憶化(哪個行得通就用哪個,一般剪枝好想把不合題目要求的刪掉就行,記憶化不太好想)
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <iomanip> 5 #include <cstdio> 6 #include <cstring> 7 #include <cmath> 8 using namespace std; 9 typedef long long ll; 10 typedef unsigned long long ull; 11 const int maxn=1e6+5; 12 int a[maxn]; 13 int vis[maxn]; 14 int N,A,B; 15 int ans=1e9; 16 int p=1; 17 18 void so(int last,int step) 19 { 20 //cout<<p++<<endl; 21 if(last==B) 22 { 23 if(ans>step) ans=step; 24 return; 25 } 26 27 int s=last+a[last],x=last-a[last]; 28 if(s<=N) { if(vis[s]==0) { vis[s]=1; so(s,step+1); vis[s]=0; } } 29 if(x>=1) { if(vis[x]==0) { vis[x]=1; so(x,step+1); vis[x]=0; } } 30 } 31 32 int main() 33 { 34 ios::sync_with_stdio(false); cin.tie(0); 35 36 cin>>N>>A>>B; 37 for(int i=1;i<=N;i++) cin>>a[i]; 38 39 vis[A]=1; 40 so(A,0); 41 42 if(ans==1e9) cout<<"-1"<<endl; 43 else cout<<ans<<endl; 44 45 return 0; 46 }
3.優化剪枝50ms過
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <iomanip> 5 #include <cstdio> 6 #include <cstring> 7 #include <cmath> 8 using namespace std; 9 typedef long long ll; 10 typedef unsigned long long ull; 11 const int maxn=1e6+5; 12 int a[maxn]; 13 int vis[maxn]; 14 int N,A,B; 15 int ans=1e9; 16 int p=1; 17 18 void so(int last,int step) 19 { 20 //p++; 21 //if(p>1e3) return; 22 if(last==B) 23 { 24 //cout<<last<<' '<<step<<endl; 25 if(ans>step) ans=step; 26 return; 27 } 28 29 int s=last+a[last],x=last-a[last];//step<=ans就是剪枝優化... 30 if(s<=N && vis[s]==0 && step<=ans) { vis[s]=1; so(s,step+1); vis[s]=0; } 31 if(x>=1 && vis[x]==0 && step<=ans) { vis[x]=1; so(x,step+1); vis[x]=0; } 32 } 33 34 int main() 35 { 36 ios::sync_with_stdio(false); cin.tie(0); 37 38 cin>>N>>A>>B; 39 for(int i=1;i<=N;i++) cin>>a[i]; 40 41 vis[A]=1; 42 so(A,0); 43 44 if(ans==1e9) cout<<"-1"<<endl; 45 else cout<<ans<<endl; 46 47 return 0; 48 }
4.附帶bfs版本27ms過,bfs和dfs遍歷搜尋所有情況的那種思路是一樣的,只不過是以廣度優先
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <iomanip> 5 #include <queue> 6 #include <cstdio> 7 #include <cstring> 8 #include <cmath> 9 using namespace std; 10 typedef long long ll; 11 typedef unsigned long long ull; 12 const int maxn=1e6+5; 13 int a[maxn]; 14 int vis[maxn]; 15 int dis[maxn];//bfs,dis陣列有記錄距離和標記作用!可以代替vis陣列 16 int N,A,B; 17 queue<int> que; 18 19 void bfs(int sx) 20 { 21 dis[sx]=0; 22 que.push(sx); 23 24 while(que.size()) 25 { 26 int p=que.front(); que.pop(); 27 if(p==B) break; 28 29 int s=p+a[p],x=p-a[p]; 30 if(s<=N && dis[s]==-1) 31 { 32 que.push(s); 33 dis[s]=dis[p]+1; 34 } 35 if(x>=1 && dis[x]==-1) 36 { 37 que.push(x); 38 dis[x]=dis[p]+1; 39 } 40 } 41 } 42 43 int main() 44 { 45 ios::sync_with_stdio(false); cin.tie(0); 46 47 cin>>N>>A>>B; 48 for(int i=1;i<=N;i++) cin>>a[i]; 49 for(int i=0;i<=1005;i++) dis[i]=-1; 50 51 bfs(A); 52 53 cout<<dis[B]<<endl; 54 55 return 0; 56 }
完。