(poj 1088 滑雪)
阿新 • • 發佈:2019-01-23
題解
- 一般的方法是記憶化搜尋。注意如果一個f[x][y]已經算過了,那麼直接返回就好了,相當於剪枝吧
- 另一種方法是非遞迴的。先按高度從小到大排序,由於這樣做依然可以保證包含最長的情況,因此是正確的,而且很快。
Code
非遞迴版
// by spli
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=110;
int n,m,cnt;
int tx[5]={0,1 ,0,-1,0};
int ty[5]={0,0,1,0,-1};
int h[N][N];
struct node{
int x,y,v;
}e[N*N];
int f[N][N];
int x,y,kx,ky;
bool cmp(node a,node b){
return a.v<b.v;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
scanf("%d",&h[i][j]);
e[++cnt].x=i;
e[cnt].y=j;
e[cnt].v=h[i][j];
}
sort(e+1 ,e+1+cnt,cmp);
for(int i=1;i<=cnt;++i){
x=e[i].x;
y=e[i].y;
f[x][y]=max(f[x][y],1);
for(int j=1;j<=4;++j){
kx=x+tx[j];
ky=y+ty[j];
if(kx>=1&&kx<=n&&ky>=1&&ky<=m&&h[kx][ky]>h[x][y]){
if (f[kx][ky]<=f[x][y]+1){
f[kx][ky]=f[x][y]+1;
}
}
}
}
int ans=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
ans=max(ans,f[i][j]);
cout<<ans;
return 0;
}
記憶化搜尋
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m;
int h[110][110];
int f[110][110];
int mx[5]={0,1,0,-1,0};
int my[5]={0,0,1,0,-1};
int ans;
int dfs(int x,int y){
if(f[x][y]) return f[x][y];
for(int i=1;i<=4;++i){
int nx=x+mx[i];
int ny=y+my[i];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&h[nx][ny]<h[x][y]){
f[x][y]=max(f[x][y],dfs(nx,ny)+1);
}
}
return f[x][y];
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
scanf("%d",&h[i][j]);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
dfs(i,j);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
ans=max(ans,f[i][j]);
}
}
cout<<ans+1<<endl;
return 0;
}