洛谷P1135奇怪的电梯(正向暴力递归+剪枝优化)

题目链接: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 }

 

加一个记忆化递归版本(额。。不知道哪有问题,只有90分,最后一个毒点WA)

 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 Ans[maxn];
15 int N,A,B;
16 int p=1;
17 
18 int so(int last)
19 {
20     if(Ans[last]!=1e7) return Ans[last];
21     if(last==B)
22     {
23         //cout<<last<<' '<<B<<endl;
24         return 0;//或者直接返回Ans[last]=0;
25     }
26 
27     int s=last+a[last],x=last-a[last];
28     int a1=1e7,a2=1e7,ans=1e7;
29     if(s<=N && vis[s]==0) { vis[s]=1; a1=so(s)+1; vis[s]=0; }
30     if(x>=1 && vis[x]==0) { vis[x]=1; a2=so(x)+1; vis[x]=0; }
31 
32     ans=min(ans,a1);
33     ans=min(ans,a2);
34 
35     Ans[last]=min(Ans[last],ans);
36     return Ans[last];
37 
38 }
39 
40 int main()
41 {
42     ios::sync_with_stdio(false); cin.tie(0);
43 
44     cin>>N>>A>>B;
45     for(int i=1;i<=N;i++) cin>>a[i];
46     for(int i=0;i<=1005;i++) Ans[i]=1e7;
47 
48     Ans[B]=0;
49     vis[A]=1;
50     int ans=so(A);
51 
52     if(ans>=1e7) cout<<"-1"<<endl;
53     else cout<<ans<<endl;
54 
55     return 0;
56 }

 

完。

 

posted @ 2018-10-20 12:08  RedBlack  阅读(261)  评论(0编辑  收藏  举报