POJ1088
以前一直想搞ACM,但一直没怎么动,没技术苦逼研究僧还是找不到工作,所以决心搞ACM,小伙伴们和我一起来学习吧。
动态规划第一题 北大ACM 1088滑雪问题
问题描述:
滑雪
Time Limit: 1000MS | Memory Limit: 65536K |
Total Submissions: 78013 | Accepted: 28994 |
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
动态规划解题描述:
首先对所有元素排序,设为a1,a2,a3 ,a4,a5,a6….
然后按照升序顺序逐次求每个元素ax的最大长度,针对每个元素对上下左右四个方向的元素与元素ax的高度比较,如果比ax大,放弃,如果比ax小,则ax经过此元素形成长度加一的最长路径。
代码:
#include <iostream>
#include <cstdlib>
using namespace std;
/*
*记录高度值(用于排序)
*记录位置row col用于寻找周围元素
*/
struct element
{
int data;
int row;
int col;
};
/*
*记录高度值和经过此点的最大长度
*/
struct arrnode
{
int high;
int mlen;
};
/*
*快排比较函数
*/
int compare( const void * ele1,const void * ele2)
{
element *ele11 = (element *)ele1;
element *ele22 = (element *)ele2;
if ( ele11->data< ele22->data )
return -1;
else if( ele11->data ==ele22->data )
return 0;
else
return 1;
}
/*
*分别从上下左右四个方向查看与row行col列元素x相邻的四个元素
*在四个元素中找高度值小于x并且长度最大的长度赋值给x的长度
*/
int Around_Max_length(int row, int col, arrnode * arr,int arrrow, int arrcol)
{
int max = 1;
int value = (*(arr+row*arrcol+col)).high;
int tvalue = 0;
int tlen = 0;
if( (col – 1) >= 0 )
{
tvalue = (*(arr+row*arrcol+col-1)).high;
tlen = (*(arr+row*arrcol+col-1)).mlen;
if( value > tvalue)
max <(tlen+1) ? max=(tlen+1) : max = max;
}
if( (row – 1) >= 0 )
{
tvalue = (*(arr+(row-1)*arrcol+col)).high;
tlen = (*(arr+(row-1)*arrcol+col)).mlen;
if( value > tvalue)
max <(tlen+1) ? max=(tlen+1) : max = max;
}
if( (row + 1) < arrrow )
{
tvalue = (*(arr+(row+1)*arrcol+col)).high;
tlen = (*(arr+(row+1)*arrcol+col)).mlen;
if( value > tvalue)
max <(tlen+1) ? max=(tlen+1) : max = max;
}
if( (col + 1) < arrcol )
{
tvalue = (*(arr+row*arrcol+col+1)).high;
tlen = (*(arr+row*arrcol+col+1)).mlen;
if( value > tvalue)
max <(tlen+1) ? max=(tlen+1) : max = max;
}
return max;
}
int main()
{
int r = 0 , c = 0 ;
cin>>r>>c;
arrnode * arr_high = new arrnode[r*c];
element * listele = new element[r*c];
int listnum = 0;
//初始化
for ( int i = 0; i < r;i++ )
{
for ( int j = 0; j < c;j++ )
{
int t = 0;
cin>>t;
arrnode arn = {t,1};
arr_high[listnum]= arn;
element elet = {t,i,j};
listele[listnum++]= elet;
}
}
//快排
qsort(listele,r*c,sizeof(element),compare );
//对有序数组listele的每个元素依次计算其最大长度记录于arr_high用于以后计算的子问题的解
for(int k = 0; k < r*c;k++ )
{
element fmlele =listele[k];
int row = fmlele.row;
int col = fmlele.col;
arr_high[row*c+col].mlen= Around_Max_length(row,col,arr_high,r,c);
}
//遍历数组arr_high寻找最大长度
int max = 0;
for(int m = 0; m < r*c;m++ )
{
max <arr_high[m].mlen ? max = arr_high[m].mlen : max=max;
}
cout<<max<<endl;
int kk;
cin>>kk;
return 0;
}