POJ 1088 滑雪

由简单的开始学习DP,参考他人的DP题目列表,于是找最简单的题目做。照我这个年纪,做这种题目会不会很丢人,暂且不管之。

POJ 1088 题目链接

递归的定义的话,从“区域最长的”高度 H 点往下滑,滑到上下左右的某一个 H-1 点处,则 H-1 位置处也是上下左右4个点中 “区域最长的”点。

原因很简单:如果 H-1 处不是“区域最长的”点,那么可以从上下左右4个点中另外取1个“区域最长的”点作为滑下的点,加上 H 点区域会变得更长。与之前 H 点上“区域最长的”点矛盾。

则递归表达式大致是:

f(h) = f(h-1)+1 ;       if h!=1
f(h) = 1;               if h==1

递归后会造成无数次的重复,效率太低。很典型的DP问题,自底向上则会使效率快很多。

大致伪代码:

for H 点 in 从小到大排序的高度
{
    for M 点 in 矩阵中所有的点
    {
        for N 点 in M点的上下左右的4个点
        {
            if (N点的高度>M点的高度 && N点的最长区域<M点最长区域+1)
                N点的最长区域 = M点最长区域+1;
        }
    }
}
遍历矩阵中所有的点,找出区域最长的点,输出

我的源代码如下:

   1: #include <iostream>
   2: using namespace std;
   3: const int ITEM_SIZE = 10001;
   4: const int ARR_SIZE = 100;
   5:  
   6: struct ItemNode
   7: {
   8:     int hight;
   9:     int length;
  10: };
  11: ItemNode item[ARR_SIZE][ARR_SIZE];
  12: void initItem()
  13: {
  14:     for (int i=0; i<ARR_SIZE; i++)
  15:     {
  16:         for (int j=0; j<ARR_SIZE; j++)
  17:         {
  18:             item[i][j].hight = 0;
  19:             item[i][j].length = 0;
  20:         }
  21:     }
  22: }
  23:  
  24: int main()
  25: {
  26:     initItem();
  27:     int row=0, column=0;
  28:     int maxHight=0, minHight=ITEM_SIZE-1;
  29:     cin >> row >> column;
  30:     if (row<=0 || column<=0 || row>ARR_SIZE || column>ARR_SIZE)
  31:         return -1;
  32:     
  33:     for (int i=0; i<row; i++)
  34:     {
  35:         for (int j=0; j<column; j++)
  36:         {
  37:             cin >> item[i][j].hight;
  38:             maxHight = maxHight<item[i][j].hight ? item[i][j].hight : maxHight;
  39:             minHight = minHight>item[i][j].hight ? item[i][j].hight : minHight;
  40:         }
  41:     }
  42:     
  43:     for (int hight=minHight; hight<=maxHight; hight++)
  44:     {
  45:         for (int i=0; i<ARR_SIZE; i++)
  46:         {
  47:             for (int j=0; j<ARR_SIZE; j++)
  48:             {
  49:                 if (item[i][j].hight==hight)
  50:                 {
  51:                     if (i-1>=0 && item[i-1][j].hight>item[i][j].hight && item[i-1][j].length<item[i][j].length+1)
  52:                         item[i-1][j].length = item[i][j].length+1;
  53:                     if (i+1<row && item[i+1][j].hight>item[i][j].hight && item[i+1][j].length<item[i][j].length+1)
  54:                         item[i+1][j].length = item[i][j].length+1;
  55:                     if (j-1>=0 && item[i][j-1].hight>item[i][j].hight && item[i][j-1].length<item[i][j].length+1)
  56:                         item[i][j-1].length = item[i][j].length+1;
  57:                     if (j+1<column && item[i][j+1].hight>item[i][j].hight && item[i][j+1].length<item[i][j].length+1)
  58:                         item[i][j+1].length = item[i][j].length+1;
  59:                 }
  60:             }
  61:         }
  62:     }
  63:     int res = 0;
  64:     for (int i=0; i<ARR_SIZE; i++)
  65:     {
  66:         for (int j=0; j<ARR_SIZE; j++)
  67:         {
  68:             res = res<item[i][j].length ? item[i][j].length:res;
  69:         }
  70:     }
  71:     cout << res+1 << endl;
  72:     return 0;
  73: }

关于测试数据,除开题目给的一组,这里另给一组,来源

4 4
1 2 2 1
1 4 4 1
1 3 3 1
1 2 2 1
输出结果很显然,为4.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值