POJ1088滑雪问题 简单dp(动态规划)已AC

来源:互联网 发布:阿里移动推荐算法代码 编辑:程序博客网 时间:2024/05/21 07:57
滑雪
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 99422 Accepted: 37756

Description

Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子 
 1  2  3  4 516 17 18 19 615 24 25 20 714 23 22 21 813 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 51 2 3 4 516 17 18 19 615 24 25 20 714 23 22 21 813 12 11 10 9

Sample Output

25
第一次做:直接输出长乘宽.....没有考虑到人家不一定按回旋型输入。只好删掉T.T第二次做:找到最高的那个滑坡,从它开始上下左右寻找最接近它高度的滑坡,以此类推,直到到最低。。。WA???然后默默想了十分钟,Oh!oh!oh!最高的滑坡不一定只有一个!!!一大堆代码,删掉。T.T第三次做:终于明白了题目深意,dp(动态规划),比如25这个滑坡,要依次考虑24,20,18,22滑坡到底端的最长路径,而例如24,又要依次考虑15,17,23到底端的最长路径……以此类推最后找到1到底端的最长路径。(str=store储存)(ski=滑雪=滑坡)(博主不知道滑坡英语是啥....)我们用一个str[101][101]数组存储对应ski[101][101]中对应滑坡各自的最优解,这样我们就没必要每次算一个滑坡的最优解都要不断递归直到底端,然后依次求出最优解,最后再得到此滑坡的最优解,这个过程会重复许多次,所以我们只需将已经算出最优解滑坡记下来,下次到这个滑坡时直接读取就好,可以省下一大笔时间(如果一直递归会超时的)何为动态规划:(博主表达能力不好,就上网搜了易懂的解释)动态规划算法的基本思想是:将待求解的问题分解成若干个相互联系的子问题,先求解子问题,然后从这些子问题的解得到原问题的解;对于重复出现的子问题,只在第一次遇到的时候对它进行求解,并把答案保存起来,让以后再次遇到时直接引用答案,不必重新求解。动态规划算法将问题的解决方案视为一系列决策的结果,与贪婪算法不同的是,在贪婪算法中,每采用一次贪婪准则,便做出一个不可撤回的决策;而在动态规划算法中,还要考察每个最优决策序列中是否包含一个最优决策子序列,即问题是否具有最优子结构性质。测试数据:3 410 9 8 2 3 310 8 15 4 343 36 6 66 6 66 6 614 41 2 2 11 3 3 11 4 4 11 2 2 141 51 2 4 3 436 68888 9999 8888 7777 7778 77768887 9000 10000 7000 7900 100008889 9001 9889 9988 7199 100004444 5555 6666 7777 7776 89893399 5555 4444 8739 9024 384310000 9999 9999 2222 1111 47487
#include <iostream>#include <algorithm>using namespace std;int r,c;//r是行,c是列int ski[101][101];//滑坡高度int str[101][101];//存储每个滑坡到地面的最长路径int dp(int row,int col);//row=行,col=列,搜索每个滑坡的最优解int main(){    memset(str,0,sizeof(str));    cin>>r>>c;    for(int i=0;i<r;i++)        for(int j=0;j<c;j++)            cin>>ski[i][j];    for(int i=0;i<r;i++)        for(int j=0;j<c;j++)            str[i][j]=dp(i,j);    int max_ski=str[0][0];    for(int i=0;i<r;i++)//找出所有滑坡中的最优解        for(int j=0;j<c;j++){            if(str[i][j]>max_ski)                max_ski=str[i][j];        }    cout<<max_ski<<endl;    return 0;}int dp(int row,int col){    if(str[row][col])return str[row][col];//如果已经有最优解就直接返回    else{        //这里的max是为了取当前row,col情况下最优解        if(row-1>=0&&ski[row-1][col]<ski[row][col])//上            str[row][col]=max(str[row][col],1+dp(row-1,col));//寻找上面滑坡的最优解        if(row+1<r&&ski[row+1][col]<ski[row][col])//下            str[row][col]=max(str[row][col],1+dp(row+1,col));        if(col-1>=0&&ski[row][col-1]<ski[row][col])//左            str[row][col]=max(str[row][col],1+dp(row,col-1));        if(col+1<c&&ski[row][col+1]<ski[row][col])//右            str[row][col]=max(str[row][col],1+dp(row,col+1));        return str[row][col]?str[row][col]:1;//如果不等于0说明有比它小的滑坡,如果等于0说明,其余滑坡都大等于它    }}


 
原创粉丝点击