题目链接:http://poj.org/problem?id=1088点击打开链接
题目描述:好吧,这熊孩纸要滑雪,他得从地图上高的地方往低的地方滑,可以滑向上下左右四个方向相邻的格,问最长路径多长?
题目里给出地图的,差不多酱紫:
5 3
2 10 2
1 2 2
2 5 6
3 4 7
1 9 8
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
解题思路:先说dp的解题思路吧,我的代码是这样想的,用dp[ i ] [ j ] 表示从该点往下滑的最长路径。dp[ i ] [ j ]等于{[i-1][ j ] / [i][j-1] / [i+1][ j ] / [ i ][j+1]}这四个位置中比[ i ][ j ]高度低的之中dp值最大的一个dp[某][某]+1。如果这四个点都比[ i ][ j ]高度大,那么dp[ i ][ j ]=1。我们还需要用结构体来存地图,按高度给结构体排序,按升序得到每点的dp值。
我的代码:
我觉得test函数还是挺有必要的。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct node
{
int x;
int y;
int h;
};
int R,C;
node grid[10100];
int dp[120][120];
int realmap[120][120];
int dx[]={0,0,1,-1},
dy[]={1,-1,0,0};
bool cmp(node a,node b)
{
return a.h<b.h;
}
void test()
{
int i,j;
for(i=0;i<R;i++)
{
for(j=0;j<C;j++)
cout<<realmap[i][j]<<" ";
cout<<endl;
}
cout<<endl;
for(i=0;i<R*C;i++)
{
cout<<grid[i].x<<" "<<grid[i].y<<" "<<grid[i].h<<endl;
}
cout<<endl;
for(i=0;i<R;i++)
{
for(j=0;j<C;j++)
cout<<dp[i][j]<<" ";
cout<<endl;
}
}
int ok(int x,int y)
{
if(x>=0&&x<R&&y>=0&&y<C)
return 1;
return 0;
}
void deal(node xx)
{
int i,flag=0,tx,ty;
int maximum=0;
for(i=0;i<4;i++)
{
tx=xx.x+dx[i];ty=xx.y+dy[i];
if(ok(tx,ty)&&realmap[tx][ty]<realmap[xx.x][xx.y]&&dp[tx][ty]>maximum)
{
maximum=dp[tx][ty];
flag=1;
}
}
if(flag)
dp[xx.x][xx.y]=maximum+1;
else
dp[xx.x][xx.y]=1;
}
int main()
{
//freopen("1088test.txt","r",stdin);
cin>>R>>C;
int i,j,cc=-1;
memset(grid,0,sizeof(grid));
memset(realmap,0,sizeof(realmap));
memset(dp,0,sizeof(dp));
for(i=0;i<R;i++)
{
for(j=0;j<C;j++)
{
cin>>realmap[i][j];
grid[++cc].x=i;
grid[cc].y=j;
grid[cc].h=realmap[i][j];
}
}
sort(grid,grid+R*C,cmp);
for(i=0;i<R*C;i++)
{
deal(grid[i]);
}
//test();
int ans=0;
for(i=0;i<R;i++)
{
for(j=0;j<C;j++)
if(dp[i][j]>ans)ans=dp[i][j];
}
cout<<ans<<endl;
return 0;
}
侯鑫同学的代码:
侯鑫大神的代码!0ms!比我短一半!牛逼。膜拜
#include<stdio.h>
#include<string.h>
int mm[105][105],r,c;
int len[105][105],dx[4]={0,0,1,-1},dy[4]={1,-1,0,0},vis[105][105];
int dp(int i,int j)
{
int max=0,n,m,l;
if(vis[i][j])return len[i][j];
else {
for(n=0;n<4;n++){
m=mm[i][j]-mm[i+dx[n]][j+dy[n]];//printf("%d",n);
if(m<=0||i+dx[n]<0||i+dx[n]>=r||j+dy[n]<0||j+dy[n]>=c)continue;
l=dp(i+dx[n],j+dy[n]);
if(1+l>max)max=1+l;
}
len[i][j]=max;
vis[i][j]=1;
return max;
}
}
int main()
{
memset(vis,0,sizeof(vis));
memset(len,0,sizeof(len));
scanf("%d%d",&r,&c);
int i,j,max=0;
for(i=0;i<r;i++)
for(j=0;j<c;j++)
scanf("%d",&mm[i][j]);
for(i=0;i<r;i++)
for(j=0;j<c;j++)
{
len[i][j]=dp(i,j);
if(len[i][j]>max)max=len[i][j];
}
printf("%d",max+1);
return 0;
}
网上的DFS代码:
网上看到的超神器的DFS代码,非常有借鉴意义!
那个MARK数组出神入化了有木有!
#include<iostream>
#include <cstdio>
using namespace std;
int x,y;
int map[100][100];
int mark[100][100]={0};
int all=0;
int dfs(int i,int j)
{
int k;
if(mark[i][j]) return mark[i][j];
if(i!=0&&map[i-1][j]<map[i][j]) {k=dfs(i-1,j)+1;if(k>mark[i][j]) mark[i][j]=k;}
if(i!=x-1&&map[i+1][j]<map[i][j]) {k=dfs(i+1,j)+1;if(k>mark[i][j]) mark[i][j]=k;}
if(j!=0&&map[i][j-1]<map[i][j]) {k=dfs(i,j-1)+1;if(k>mark[i][j]) mark[i][j]=k;}
if(j!=y-1&&map[i][j+1]<map[i][j]) {k=dfs(i,j+1)+1;if(k>mark[i][j]) mark[i][j]=k;}
return mark[i][j];
}
int main()
{
//freopen("1088test.txt","r",stdin);
int i,j;
cin>>x>>y;
for(i=0;i<x;i++)
for(j=0;j<y;j++)
cin>>map[i][j];
int max=0,k;
for(i=0;i<x;i++)
for(j=0;j<y;j++)
{
k=dfs(i,j);
if(k>max) max=k;
}
cout<<max+1<<endl;
return 0;
}