关于滑雪问题的一些解法(综合自网络)

1icon-default.png?t=M3K6https://www.shuzhiduo.com/A/Ae5RkboLdQ/

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=105,mod=1e9+7;
int a[N][N];
int n,m;
int tmp;
 
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int h[N][N];//记录坐标(i,j)的答案,以(i,j)为起点的路径最长多少 
 
int dfs(int x,int y){//以(x,y)为起点的遍历
    int mx=0;
    if(h[x][y])return h[x][y];// 记录为0的路径避免重复计算
    for(int i=0;i<4;i++){
        int nx=x+dx[i],ny=y+dy[i];
        if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&a[nx][ny]<a[x][y]){//递归出口:找不到更低的去处
            mx=max(mx,dfs(nx,ny));//递归体:只要能在周围找到能去的路径,递归调用去找能去路径的最大值
        }
    }
    return h[x][y]=mx+1;//最终求出周围路径最大值+1就是(x,y)为起点的最长滑坡长度
}
// dfs: 这个算法会尽可能深的搜索树的分支 ,#include<cstdio>
#include<algorithm>
using namespace std;
const int N=105,mod=1e9+7;
int a[N][N];
int n,m;
int tmp;
 
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int h[N][N];//记录坐标(i,j)的答案,以(i,j)为起点的路径最长多少 
 
int dfs(int x,int y){//以(x,y)为起点的遍历
    int mx=0;
    if(h[x][y])return h[x][y];// 记录为0的路径避免重复计算
    for(int i=0;i<4;i++){
        int nx=x+dx[i],ny=y+dy[i];
        if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&a[nx][ny]<a[x][y]){//递归出口:找不到更低的去处
            mx=max(mx,dfs(nx,ny));//递归体:只要能在周围找到能去的路径,递归调用去找能去路径的最大值
        }
    }
    return h[x][y]=mx+1;//最终求出周围路径最大值+1就是(x,y)为起点的最长滑坡长度
}
// dfs: 这个算法会尽可能深的搜索树的分支 ,时间复杂度为O(N)
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            dfs(i,j);
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            ans=max(ans,h[i][j]);
        }
    }
    printf("%d\n",ans);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            dfs(i,j);
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            ans=max(ans,h[i][j]);
        }
    }
    printf("%d\n",ans);
}

2icon-default.png?t=M3K6https://cloud.tencent.com/developer/article/1732131

#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
#define mst(a,b)  memset((a),(b),sizeof(a));
const int max1=105;
long long int dp[max1][max1];
//int sum[max1];
long long int ob[max1][max1];
int dx[5]={0,-1,0,1,0},
    dy[5]={0,0,-1,0,1};
    //dx与dy一组,构成上下左右四个方向
long long int r,//长
            c,//宽
            t,//做中间变量,用来寻找最大的ans
            ans;//预设答案变量
int search(int x,int y);//声明search函数
int main()
{
    cin>>r>>c;//输入长宽
    ans=0;//无合适条件下设ans为最小值0
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
            cin>>ob[i][j];//输入矩阵
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++){//遍历矩阵中每一个点
            t=search(i,j);//调用searc函数
            dp[i][j]=t;
            if(t>ans) ans=t;
        }
        cout<<ans<<endl;
}
int search(int x,int y)
{
    int w,tmp,nx,ny;
    if(dp[x][y]>0){ //如果dp大于0代表dp被调用过可以直接使用
        return(dp[x][y]);//返回dp[i][j]的值
    }
    w=1;
    for(int i=1;i<=4;i++){//遍历四个方向
        nx=x+dx[i];
        ny=y+dy[i];
        if((nx>=1)&&(nx<=r)&&(ny>=1)&&(ny<=c)&&(ob[x][y]<ob[nx][ny])){//边界
            tmp=search(nx,ny)+1;//递归求当前点能够到达的最大值
            if(tmp>w) w=tmp;
        }
    }
        dp[x][y]=w;
        return w;
}
/*
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
*/

3icon-default.png?t=M3K6https://blog.csdn.net/u011797040/article/details/88752799

#include<cstdio>
#include<iostream>
#include<algorithm>
#define SIZE 101
using namespace std;
int dfs(int i, int j);
int maze[SIZE][SIZE] = {0}; 
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
int dp[SIZE][SIZE];
int ans = 0;
int r,c;
int main(void){
	//输入 
	cin >> r >> c;
	for(int i = 0; i < r; i++){
		for(int j = 0; j < c; j++){
			cin >> maze[i][j];
		}
	}
	
/*	for(int i = 0; i < r; i++){
		for(int j = 0; j < c; j++){
			printf("%d ",maze[i][j]);
		}
		printf("\n");
	}
*/
	//处理 
	for (int i = 0; i < r; i++){
		for(int j = 0; j < c; j++){
		//	printf("%6d\n", t);
			int t = dfs(i,j);
			if (ans < t)
				ans = t;
		}
	}
	printf("%d\n", ans);
	return 0;
}

int dfs(int i, int j){

	if(dp[i][j])
		return dp[i][j];
	dp[i][j] = 1; 
	for(int a = 0; a < 4; a++){
		int x = j + dx[a], y = i + dy[a];
		if(x >= 0 && x < c && y >= 0 && y < r && maze[y][x] < maze[i][j]){
			dp[i][j] = max(dp[i][j], dfs(y, x) + 1);//走或不走,走就长度+1 
		}
	}
	return dp[i][j];
}
————————————————
版权声明:本文为CSDN博主「Vison307」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011797040/article/details/88752799

4icon-default.png?t=M3K6https://blog.csdn.net/qq_31638535/article/details/83274584

#include <iostream>
#include<cstdio>
#include <time.h>
#include <cstring>
 
int h[100][100]={0};   高度图
int count[100][100]={0};  ///记录每一个高点的最大滑雪长度
int f[][2]={{1,0},{0,1},{-1,0},{0,-1}};  ///这个在注释的代码有用,在做dfs的时候用这个,整个的dfs会显得简洁
int r,c;
int max_line = 0;
 
int find(int i,int j)
{
    int max_t=0;
    if(count[i][j]>0)
        return count[i][j];
    /up search
    if(i-1>=0)
    {
        if(h[i-1][j]<h[i][j])
        {
            max_t = std::max(find(i-1,j),max_t);
        }
    }
    /down search
    if(i+1<r)
    {
        if(h[i+1][j]<h[i][j])
        {
            max_t = std::max(find(i+1,j),max_t);
        }
    }
    left search
    if(j-1>=0)
    {
        if(h[i][j-1]<h[i][j])
           max_t = std::max(find(i,j-1),max_t);
    }
    //right search
    if(j+1<c)
    {
        if(h[i][j+1]<h[i][j])
        {
            max_t = std::max(find(i,j+1),max_t);
        }
    }
///如果用下面的代码,那么这个函数以上四个遍历都可以注释掉了,这个是我参考网友的写法写的比较简洁,但思路一样,并不影响速度
//    for ( int z = 0 ; z < 4 ; z ++ )
//    {
//        int s = i + f[z][0] ;
//        int t = j + f[z][1] ;
//        if ( s < 0 || t < 0 || s >= r || t >= c )
//            continue;
//        if ( h[s][t] >= h[i][j] )
//            continue;
//        max_t = std::max ( max_t , find ( s , t ) ) ;
//    }
    count[i][j]=max_t+1;    /关键步骤,记下每一次深度搜索的结果,避免重复搜索
    return max_t+1; /如以上没有一个满足条件,就可以直接+1,由于递归,所以只要是经过的点都+1,刚好记录下深度信息
}
int main() {
    memset( count , -1 , sizeof ( count ) );
    scanf("%d%d", &r, &c);  scanf 是以回车一下作为输入数据的间隔
    printf("input h data");
    for (int i = 0; i < r; i++)
        for (int j = 0; j < c; j++)
        {
            scanf("%d", &h[i][j]);
   //           h[i][j]=i+j;
 
        }
    clock_t start=clock();
    int ans = 0;
    for (int i = 0; i < r; i++)
        for (int j = 0; j < c; j++)
        {
            count[i][j]=find(i,j);
            ans = std::max(ans, count[i][j]);
        }
    clock_t end=clock();
    std::cout<<"cost time :"<<double(end-start)/CLOCKS_PER_SEC*1000 <<"s"<<std::endl;
    printf("%d", ans);
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zeng-fh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值