1. 程式人生 > >洛谷P1135奇怪的電梯(正向暴力遞歸+剪枝優化)

洛谷P1135奇怪的電梯(正向暴力遞歸+剪枝優化)

ostream amp turn new stream man 情況 很多 www

題目鏈接: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 }

完。

洛谷P1135奇怪的電梯(正向暴力遞歸+剪枝優化)