试题链接:https://vjudge.net/problem/POJ-1088 这道题肯定最先想到是DFS跟BFS,但是数据是100*100,还要每个点都进行搜索,肯定会超时。 但是我为了巩固DFS跟BFS,把这道题的BFS跟DFS都码了一遍,如果这道题数据没有这么大的话,肯定是可以的。 下面的代码是BFS跟DFS的代码,都TE了。 TE BFS #include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <vector> #include <stack> #include <sstream> #include <map> #include <set> #include <queue> using namespace std; int a[1005][1005]; int b[1005][1005]; int shu1[10]={0,1,-1,0,0}; int heng1[10]={0,0,0,1,-1}; struct sss { int shu; int heng; int step; }l; int n,m; int BFS(int x,int y) { int ans=1; queue<sss>ss; ss.push({x,y,1}); while(!ss.empty()) { l=ss.front(); ss.pop(); ans=max(ans,l.step); for (int i=1;i<=4;i++) { int s=l.shu+shu1[i]; int h=l.heng+heng1[i]; if(s>0&&s<=n&&h>0&&h<=m) { if(a[s][h]<a[l.shu][l.heng]) ss.push(sss{s,h,l.step+1}); } } } return ans; } int main () { cin >> n >> m; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { cin >> a[i][j]; } } for (int i=1;i<=n;i++) //这一段可以跟下面的for循环结合,代码就会短很多。sum=max(sum,BFS(i,j) { for (int j=1;j<=m;j++) { b[i][j]=BFS(i,j); } } int sum=1; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { sum=max(sum,b[i][j]); } } cout << sum << endl; return 0; } TL DFS #include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <vector> #include <stack> #include <sstream> #include <map> #include <set> #include <queue> using namespace std; int a[1005][1005]; int b[1005][1005]; int shu[10]={1,-1,0,0}; int heng[10]={0,0,-1,1}; int n,m,sum; int DFS(int x,int y,int z) { sum=max(sum,z); for (int i=0;i<=3;i++) { int s=x+shu[i]; int h=y+heng[i]; if(s>0&&s<=n&&h>0&&h<=m) { if(a[s][h]<a[x][y]) DFS(s,h,z+1); } } return sum; } int main () { cin >> n >> m; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { cin >> a[i][j]; } } for (int i=1;i<=n;i++) //这一段可以跟下面的for循环结合,代码就会短很多,ans=max(ans,DFS(i,j,1) { for (int j=1;j<=m;j++) { sum=1; b[i][j]=DFS(i,j,1); } } int ans=1; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { ans=max(ans,b[i][j]); } } cout << ans << endl; return 0; } 下面的代码才是可以AC的代码,也是每一个点都进行遍历,找他四周的点,如果比他小的话,就递归再次进行遍历,最后记录下来这个点的最大二维下降子序列的长度。 如果比他小的那个点在上述步骤中已经遍历过了,则直接用他记录下来的值就可以了,这样就减少了时间复杂度,不会被超时。 #include <cstdio> #include <iostream> #include <algorithm> using namespace std; int a[105][105]; int b[105][105]; int shu1[10]={0,1,-1,0,0}; int heng1[10]={0,0,0,1,-1}; int n,m; int DP(int x,int y) { int sum=0; if(b[x][y]!=0) //遍历结束的条件 { return b[x][y]; } for (int i=1;i<=4;i++) { int s=x+shu1[i]; int h=y+heng1[i]; if(a[s][h]<a[x][y]&&s>0&&s<=n&&h>0&&h<=m) { sum=max(sum,DP(s,h)); } } b[x][y]=sum+1; return b[x][y]; } int main () { cin >> n >> m; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { cin >> a[i][j]; } } int ans=1; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { ans=max(ans,DP(i,j)); } } cout << ans << endl; return 0; }