滑雪问题的几个解法

来源:互联网 发布:怎样修改淘宝退款金额 编辑:程序博客网 时间:2024/05/17 23:34
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
输出最长区域的长度。


      最初看到这个问题,是在(
http://www.cppblog.com/qywyh/archive/2006/03/01/3616.aspx) ,下面是该blog 作者的一个解法:  这个解法中的回溯很经典,在回溯中运用动态规划,代码如下:

#include <iostream>
using namespace std;

const int MAX = 102;
const int HIGHT = 10001;
struct pos {
    int i, j , p ;
};
int path(int [MAX][MAX], int [MAX][MAX] , int [MAX][MAX], int , int) ;

int main(int argc,char * argv[])
{
    int input[MAX][MAX];
    int result[MAX][MAX];
    int status[MAX][MAX];
    int m,n;

    int i,j;
    int max, ans;
    cin >> m >> n;
    for(i = 0 ; i <= m + 1; i ++)
        for(j = 0 ; j <= n + 1; j ++)
        {
            input[i][j] = HIGHT ;
            result[i][j] = 0;
            status[i][j] = 0;
        }
    for(i = 1; i <= m ; i++)
        for(j = 1; j <= n ; j++)
            cin >> input[i][j];
    clock_t  t1 = clock();
    for(i = 1; i <= m ; i++)
        for(j = 1; j <= n ;j ++)
            path(input,result,status,i,j);
    max = 0;
    for(i = 1; i <= m ; i++)
        for(j = 1; j <= n ; j ++)
            if( max < result[i][j])
                max = result[i][j];
    clock_t t2 = clock();
    cout <<"Time is : " << t2 - t1 <<endl;
    cout << max <<endl;
    return 0;
}

int path(int input[MAX][MAX], int result[MAX][MAX], int status[MAX][MAX],int i , int j)
{
    pos pack[MAX * MAX];
    int max,g,h;
    int ii;
    int top = 0;
    int p = 0;
    int incr[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
    if(result[i] [ j] > 0 ) return 0;
    else {
        pack[top].i = i;
        pack[top].j = j;
        pack[top].p = p;
        status[i][j] = - 1;
    }
    while(top >= 0 || p < 4) {
        if(p < 4) {
            g = pack[top].i + incr[p][0];
            h = pack[top].j + incr[p][1] ;

            if(input[pack[top].i][pack[top].j] > input[g][h] )
            {
                if(result[g][h] > 0 || status[g][h] == -1)
                    p ++;
                else {
                    top ++ ;
                    pack[top].i = g;
                    pack[top].j = h;
                    pack[top].p = p;
                    status[g][h] = -1;
                    p = 0 ;
                }
            }
            else p++;
        } else {
            max = 0;
            for(ii = 0 ; ii < 4; ii ++) {
                g = pack[top].i + incr[ii][0];
                h = pack[top].j + incr[ii][1];
                if(input[pack[top].i][pack[top].j] > input[g][h] && max < result[g][h])
                    max = result[g][h];
            }
            result[pack[top].i][pack[top].j] = max + 1;
            top --;
            p = pack[top].p + 1;
        }
    }
    return 0;
}

   


     这个问题,可以完全用递归来解决,感这个问题完全用递归来解决好像比上面两种解法快一些:

#include <iostream>

using namespace std;
int hight[100][100]
;
int R,C ;
bool inline left_lower(int row,int col)
{
    
if(col >= 1) {
        
if(hight[row][col - 1< hight[row][col]) return true;
        
return false;
    }
    
return false;
}
bool inline right_lower(int row,int col)
{
    
if(col + 1 >= C) return false;
    
if(hight[row][col+1< hight[row][col]) return true;
        
return false;    
}
bool inline up_lower(int row,int col)
{
    
if(row >= 1) {
        
if(hight[row-1][col] < hight[row][col]) return true;
        
return false;
    }
    
return false;
}
bool down_lower(int row, int col)
{
    
if(row + 1 >= R) return false;
    
if(hight[row+1][col] < hight[row][col]) return true;
    
return false;
}
int step(int row, int col)
{
    
if(row < 0 || col < 0 ) return 0;
    
if(row >= R || col >= C) return 0;
    
int m = 0 ;
    
int tmp  = -1;
    
if(left_lower(row,col) == true) {
        tmp 
= step(row ,col - 1);
    }
    
if( tmp > m ) m = tmp;
    
if(right_lower(row,col) == true) {
        tmp 
= step(row,col+1);
    }
    
if(tmp > m ) m = tmp;
    
if(up_lower(row,col) == true) {
        tmp 
= step(row-1,col);
    }
    
if(tmp>m) m = tmp ;
    
if(down_lower(row,col) == true) {
        tmp 
= step(row+1,col);
    }
    
if(tmp > m) m = tmp;
    
return m + 1;
}
int main()
{
    
int i,j;
    
int max = 0 ;
    
int tmp;
    cin 
>>>> C ;
    
for(i = 0 ; i < R ; i ++)
        
for(j = 0 ; j < C ; j++)
            cin 
>> hight[i][j];
    clock_t t1 
= clock();
    
for( i = 0 ; i < R; i ++)
        
for (j = 0 ; j < C ; j ++)
        {
            
//printf("[%d,%d] =%d ", i+1,j+1,step(i,j));
            tmp = step(i,j);
            
if(tmp > max) {
                max 
= tmp;
            }
        }
    clock_t t2 
= clock();
    cout 
<< "Time is : " << t2 -t1 <<endl;
    
out <<"The max is :   " << max <<endl;
   
return 0;                
}

      附上生成测试数据的小程序:
#include <iostream>
#include 
<cstdio>
#include 
<ctime>

using namespace std;
int main(int argc,char * argv[])
{
    
int i ,j , tmp ;
    
int m,n;
    
if(argc != 3) {
        cerr 
<< "please input row-col" <<endl;
        exit(
0);
    }
    
//cin >> m >>n;
    m = atoi(argv[1]);
    n 
= atoi(argv[2]);
    cout 
<< m << ' '<< n << endl;
    srand(time(NULL));
    
for ( i = 0 ; i < m; i++) {
        
for(j = 0; j < n; j ++)
        {
            tmp 
= 0 ;
            
while(tmp == 0) {
             tmp 
= rand() % 10000;
             srand(time(NULL) 
+ tmp);
            }
            cout 
<< tmp << ' ';
        }
        cout 
<<endl;
    }
    
return 0;

}


原创粉丝点击