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