P1434 [SHOI2002] 滑雪https://www.luogu.com.cn/problem/solution/P1434
优先队列+dp
本题状态转移方程一目了然
为了保证状态间无后效性,即当前保存的就是这个位置作为终点最长的路径长度。为了保证这一点我们从最大的数开始dp,并从大到小依次进行。我们可以用优先队列来实现这个操作。
// #pragma GCC optimize (2)
// #pragma G++ optimize (2)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#define endl '\n'
#define int long long
#define lowbit(x) x &(-x)
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define TLE(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);}
using namespace std;
typedef long long ll;
const int N = 1e2+10;
struct node
{
int a,b,c;
bool operator < (const node &w)const{
return c<w.c;
}
};
priority_queue<node,vector<node>,less<node>>q;
int a[N][N],f[N][N];
int dx[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
void solve()
{
int n,m;
cin>>n>>m;
rep(i,1,n)
{
rep(j,1,m)
{
cin>>a[i][j];
f[i][j]=1;
q.push({i,j,a[i][j]});
}
}
int maxx=-2e9;
while(q.size())
{
auto t=q.top();q.pop();
int i=t.a,j=t.b;
for(int p=0;p<4;p++)
{
int x=i+dx[p][0],y=j+dx[p][1];
if(x<=0||y<=0||x>n||y>m)continue;
if(a[i][j]<a[x][y])f[i][j]=max(f[i][j],f[x][y]+1);
}
maxx=max(maxx,f[i][j]);
}
cout<<maxx<<endl;
}
signed main()
{
TLE();
int T;
T=1;
//scanf("%lld", &T);
while (T--)solve();
return 0;
}
记忆化DFS
暴力搜索一定会超时,记忆化搜索可以搜得从位置出发的所能到达的最远的距离,也就是会找到一个从当前位置出发能找到最大的数,且这个最大的数与可能存在的比他大的数并不相连,然后递归回溯过程中就会更新路径上每个值,这就保证了每个在被更新过一次后,其值即为 位置作为终点最长的路径长度。
// #pragma GCC optimize (2)
// #pragma G++ optimize (2)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#define endl '\n'
#define int long long
#define lowbit(x) x &(-x)
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define TLE() \
{ \
ios::sync_with_stdio(false); \
cin.tie(0); \
cout.tie(0); \
}
using namespace std;
typedef long long ll;
const int N = 1e2 + 10;
int n, m;
int a[N][N], f[N][N] = {0};
int dx[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int dfs(int i, int j)
{
if (f[i][j])
return f[i][j];
f[i][j] = 1;
for (int p = 0; p < 4; p++)
{
int x = i + dx[p][0], y = j + dx[p][1];
if(x<=0||y<=0||x>n||y>m)continue;//判断边界
if (a[x][y] > a[i][j])
f[i][j] = max(f[i][j], dfs(x, y) + 1);
}
return f[i][j];
}
void solve()
{
cin >> n >> m;
rep(i, 1, n)
rep(j, 1, m)
cin >>a[i][j];
int maxx = -2e9;
rep(i, 1, n)
rep(j, 1, m) maxx = max(maxx, dfs(i, j));
cout << maxx << endl;
}
signed main()
{
TLE();
int T;
T = 1;
// scanf("%lld", &T);
while (T--)
solve();
return 0;
}