POJ 1088.滑雪

17 篇文章 0 订阅

POJ 1088.滑雪

Description

Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子 
 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

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
Input

输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
Output

输出最长区域的长度。
Sample Input

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
Sample Output

25

从i,j出发,最长的一条道路就是上下左右四个方向最多的道路数+1,如果四周的点都比当前的点高,那么这个点的道路数就是1,递推的话不好实现,因为四周点的道路数是不知道的,所以可以用记忆化搜索

#include<vector>
#include<iostream>
#define rep(i,a,b) for(int i=(a); i<(int)(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(int)(b);++i)
using namespace std;
int n,m,nums[105][105];
vector<vector<int>> dp;
int infer(int r,int c)
{
    if(dp[r][c]>0)  return dp[r][c];
    dp[r][c]=1;
    if(r-1>=0&&nums[r-1][c]<nums[r][c])
        dp[r][c]=max(dp[r][c],infer(r-1,c)+1);
    if(r+1<n&&nums[r+1][c]<nums[r][c])
        dp[r][c]=max(dp[r][c],infer(r+1,c)+1);
    if(c-1>=0&&nums[r][c-1]<nums[r][c])
        dp[r][c]=max(dp[r][c],infer(r,c-1)+1);
    if(c+1<m&&nums[r][c+1]<nums[r][c])
        dp[r][c]=max(dp[r][c],infer(r,c+1)+1);
    return dp[r][c];
}

int main()
{
    cin>>n>>m;
    rep(i,0,n)
        rep(j,0,m)
            cin>>nums[i][j];
    dp.assign(n,vector<int>(m,-1));
    int maxn=0;
    rep(i,0,n)
        rep(j,0,m)
            maxn=max(maxn,infer(i,j));
    cout<<maxn;
    return 0;
}

之所以递推不好实现就是因为四周点的道路数不知道

分析后会发现,只有该点四周的点高度比较低才能够进行计算,所以我们可以事先把所有的点从低到高排序,计算时也从低到高,这样相邻点的道路数是肯定知道的

保存的时候可以保存到,一个一维数组中,方便排序,不过注意是R个一组还是C个一组

人人为我型动态规划

通过已知的的状态的值,推算未知状态的值

#include<iostream>
#include<algorithm>
#define rep(i,a,b) for(int i=(a); i<(int)(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(int)(b);++i)
using namespace std;
static const auto io_sync_off = []() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    return nullptr;
}();

struct point
{
    int r,c,h;
    bool operator < (const point &rhs)const
    {
        return h<rhs.h;
    }
}point[10005];

int dp[105][105];
int nums[105][105];

int main()
{
    int n,m;
    cin>>n>>m;
    rep(i,0,n)
        rep(j,0,m)
        {
            cin>>nums[i][j];
            point[i*m+j].r=i;		//注意是i*m,m个一组
            point[i*m+j].c=j;
            point[i*m+j].h=nums[i][j];
            dp[i][j]=1;
        }
    sort(point,point+n*m);
    rep(i,0,n*m)
    {
        int r=point[i].r;
        int c=point[i].c;
        if(r>0&&nums[r-1][c]<nums[r][c])
            dp[r][c]=max(dp[r][c],dp[r-1][c]+1);
        if(r+1<n&&nums[r+1][c]<nums[r][c])
            dp[r][c]=max(dp[r][c],dp[r+1][c]+1);
        if(c>0&&nums[r][c-1]<nums[r][c])
            dp[r][c]=max(dp[r][c],dp[r][c-1]+1);
        if(c+1<m&&nums[r][c+1]<nums[r][c])
            dp[r][c]=max(dp[r][c],dp[r][c+1]+1);
    }
    int ans=0;
    rep(i,0,n)
        rep(j,0,m)
            ans=max(ans,dp[i][j]);
    cout<<ans;
    return 0;
}
我为人人型动态规划

x点状态已知,可以推算出受x点影响的点的状态

rep(i,0,n*m)
{
    int r=point[i].r;
    int c=point[i].c;
    if(r>0&&nums[r-1][c]>nums[r][c])
        dp[r-1][c]=max(dp[r-1][c],dp[r][c]+1);
    if(r+1<n&&nums[r+1][c]>nums[r][c])
        dp[r+1][c]=max(dp[r+1][c],dp[r][c]+1);
    if(c>0&&nums[r][c-1]>nums[r][c])
        dp[r][c-1]=max(dp[r][c-1],dp[r][c]+1);
    if(c+1<m&&nums[r][c+1]>nums[r][c])
        dp[r][c+1]=max(dp[r][c+1],dp[r][c]+1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值