洛谷P1434滑雪(逆向图的遍历dfs+记忆化)

题目链接:https://www.luogu.org/problemnew/show/P1434

刚开始最先想到的就是正向递归遍历,遍历所有情况方法,记录找到最长的,正向递归遍历也不难写,但会超时。

观察后,发现它是有规律的,或者说已经遍历过的点需要多次用到,那就逆向记忆化。

注意:

图的遍历,标记数组特例情况,走过了还会回去!
2 3
3 2 4
0 1 5

正向递归遍历

 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=105;
12 int a[maxn][maxn];
13 int vis[maxn][maxn];
14 int n,m;
15 int ans;
16 
17 void so(int x,int y,int step)//这题不用标记数组,>关系决定了不会回去死循环
18 {
19     if(step>ans) ans=step;
20 
21     //
22     if(y+1<=m && a[x][y]<a[x][y+1]) { so(x,y+1,step+1); }
23     //
24     if(x+1<=n && a[x][y]<a[x+1][y]) { so(x+1,y,step+1); }
25     //
26     if(x-1>=1 && a[x][y]<a[x-1][y]) { so(x-1,y,step+1); }
27     //
28     if(y-1>=1 && a[x][y]<a[x][y-1]) { so(x,y-1,step+1); }
29 }
30 
31 int main()
32 {
33     ios::sync_with_stdio(false); cin.tie(0);
34 
35     cin>>n>>m;
36     for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
37 
38     for(int i=1;i<=n;i++)
39     {
40         for(int j=1;j<=m;j++)
41         {
42             so(i,j,1);
43         }
44     }
45 
46     cout<<ans<<endl;
47 
48     return 0;
49 }

逆向递归遍历+记忆化

 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=105;
12 int a[maxn][maxn];
13 int Ans[maxn][maxn];
14 int n,m;
15 
16 int so(int x,int y)//这题不用标记数组,>关系决定了不会回去死循环
17 {
18     if(Ans[x][y]) return Ans[x][y];
19 
20     int ans=1,a1=0,a2=0,a3=0,a4=0;
21     //
22     if(y+1<=m && a[x][y]>a[x][y+1]) a1=so(x,y+1)+1;
23     //
24     if(x+1<=n && a[x][y]>a[x+1][y]) a2=so(x+1,y)+1;
25     //
26     if(x-1>=1 && a[x][y]>a[x-1][y]) a3=so(x-1,y)+1;
27     //
28     if(y-1>=1 && a[x][y]>a[x][y-1]) a4=so(x,y-1)+1;
29 
30     ans=max(ans,a1);
31     ans=max(ans,a2);
32     ans=max(ans,a3);
33     ans=max(ans,a4);
34 
35     Ans[x][y]=max(Ans[x][y],ans);
36     return Ans[x][y];
37 }
38 
39 int main()
40 {
41     ios::sync_with_stdio(false); cin.tie(0);
42 
43     cin>>n>>m;
44     for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
45 
46     int t=0;
47     for(int i=1;i<=n;i++)
48     {
49         for(int j=1;j<=m;j++)
50         {
51             t=max(t,so(i,j));
52         }
53     }
54 
55     cout<<t<<endl;
56 
57     return 0;
58 }

完。

猜你喜欢

转载自www.cnblogs.com/redblackk/p/9816075.html