您的位置:首页 > 其它

滑雪问题的几个解法

2008-03-31 22:04 141 查看
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 >>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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: