码迷,mamicode.com
首页 > 其他好文 > 详细

集训第五周动态规划 I题 记忆化搜索

时间:2015-08-12 23:08:12      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:

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

记忆化搜索当然也还是搜索,只不过在普通的搜索上做了一些优化,因为使用的是动态规划的方法进行的优化,使得它看起来更像DP。
首先考虑如果这道题我们只是用普通搜索的方法做,那么就是从某一点开始搜索,一直搜索到最低点,不可以扩展的地方,记录下下滑的长度,那个某一点当然是不可预知的,所以得枚举,也就是说图中的每一点都要搜上一遍,请注意图最大是100*100的,超时肯定是不必说的

所以可以考虑使用dp做,dp比递归好的一个地方在于它解决了重叠子问题,这道题存在很多重叠子问题是不必说的,例如我从10出发,搜到了一条路,下一次我从25出发,等我到达10这一点时,虽然我以前走过这一条路,可是并没有把这一条路记录下来,所以还得重新再走上一遍,这样的重叠问题越多,时间浪费也就越严重,这样的浪费导致了指数级的时间复杂度,是很恐怖的

所以可以使用book【i】【j】(book在英文中有标记的意思)表示从第i行j个开始滑所能下滑的高度

那么动态规划方程为dp(i,j)=max{dp(i-1,j),dp(i+1,j),dp(i,j-1),dp(i,j+1),这些点的高度必须小于i行j列这个点的高度,否则不予考虑}+1

技术分享
#include"iostream"
#include"cstring"
using namespace std;

const int maxn=110;

int m,n,book[maxn][maxn],a[maxn][maxn];
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};

void Init()
{
    for(int i=1;i<=m;i++)
    for(int j=1;j<=n;j++)
    cin>>a[i][j];
    memset(book,-1,sizeof(book));
}

int dp(int i, int j)
{
    int k, ni, nj;
    if (book[i][j] > 0) return book[i][j];
    book[i][j] = 1;
    for (k = 0; k < 4; ++k)
    {
        ni = i + dir[k][0];
        nj = j + dir[k][1];
        if(ni>=1&&ni<=m&&nj>=1&&nj<=n&&a[i][j]>a[ni][nj]&&dp(ni,nj)+1>book[i][j])
        book[i][j] = book[ni][nj] + 1;
    }
    return book[i][j];
}


void Work()
{
    int ans=-1;
    for(int i=1;i<=m;i++)
    for(int j=1;j<=n;j++)
    if(dp(i,j)>ans) ans=book[i][j];
    cout<<ans<<endl;
   // dp(3,3);
   /* for(int i=1;i<=m;i++)
    {
    for(int j=1;j<=n;j++) cout<<book[i][j]<<" ";
    cout<<endl;
    }*/
}

int main()
{
    while(cin>>m>>n)
    {
     Init();
     Work();
    }
    return 0;
}
HOLLO

 





集训第五周动态规划 I题 记忆化搜索

标签:

原文地址:http://www.cnblogs.com/zsyacm666666/p/4725598.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!