Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个 区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
输出最长区域的长度。
最初看到这个问题,是在( 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;
}
这个问题,可以完全用递归来解决,感这个问题完全用递归来解决好像比上面两种解法快一些:
附上生成测试数据的小程序:
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。
输出最长区域的长度。
最初看到这个问题,是在( 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 >> R >> 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 ;
}
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 >> R >> 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 ;
}
#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 ;
}