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