DP:Help Jimmy[Memory recursion and recursion]

POJ 1661 Help Jimmy

Description

"Help Jimmy" is a game completed on the scene shown in the figure below: the
Insert picture description here
scene includes multiple platforms with different lengths and heights. The ground is the lowest platform, with zero height and unlimited length. The Jimmy mouse starts to fall from somewhere higher than all platforms at time 0, and its falling speed is always 1 m/s. When Jimmy falls on a certain platform, the player chooses to let it run left or right, and it runs at a speed of 1 meter per second. When Jimmy ran to the edge of the platform, he continued to fall. Jimmy cannot fall more than MAX meters, or he will fall to death and the game will end. Design a program to calculate the earliest possible time when Jimmy reaches the ground.

Input

An integer N, X, Y, MAX, separated by spaces. N is the number of platforms (not including the ground), X and Y are the horizontal and vertical coordinates of where Jimmy starts to fall, and MAX is the maximum height of a fall. Each of the next N lines describes a platform, including three integers, X1[i], X2[i] and H[i]. H[i] represents the height of the platform, and X1[i] and X2[i] represent the abscissa of the left and right end points of the platform. 1<= N <=1000, -20000<= X, X1[i], X2[i] <= 20000, 0 <H[i] <Y <= 20000 (i = 1...N). The units of all coordinates are meters. The size of Jimmy and the thickness of the platform are ignored. If Jimmy happens to fall on the edge of a platform, it is considered to be on the platform. All platforms are not overlapping or connected. The test data guarantees that Jimmy will be able to reach the ground safely.

Output

The earliest possible time when Jimmy reaches the ground.

Sample Input

1
3 8 17 20
0 10 8
0 10 13
4 14 3

Sample Output

23

Method one memory recursion

//记忆递归 
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using amespace std;
#define MAX_N 1000
#define INFINITE 1000000
int n, maxHeight;
struct Platform
{
    
    
	int Lx, Rx, h;
	bool operator < (const Platform & p) const{
    
    
		return h > p.h;
	}//重载运算符'<' 
};
Platform platForms[MAX_N + 10];
int leftMinTime[MAX_N + 10];
int rightMinTime[MAX_N + 10];

int MinTime(int num, bool Left)//num为平台编号,Left表示向左走 
{
    
    
	int y = platForms[num].h;
	int x;
	if(Left) x = platForms[num].Lx;
	else x = platForms[num].Rx;
	
	int i;
	for( i = num + 1;i <= n;i ++ ) 
	{
    
    
		if( platForms[i].Lx <= x && platForms[i].Rx >= x)
		break;//Jimmy能落到第i块板子上 
	}
	if( i <= n ) 
	{
    
    
		if( y - platForms[i].h > maxHeight )//两平台间距大于最大间距 
		return INFINITE;//Jimmy摔死 
	}
	else {
    
    //Jimmy在最后一块板子上 
		if( y > maxHeight) return INFINITE;
		else return y;
	}

	int nLeftTime = y - platForms[i].h + x - platForms[i].Lx;
//从第num块板子下降到第i块板子所需时间和从第num块板子左(右)端走到第i块板子左端花费的时间
	int nRightTime = y - platForms[i].h + platForms[i].Rx - x;
//从第num块板子下降到第i块板子所需时间和从第num块板子左(右)端走到第i块板子右端花费的时间 
	
	if(!leftMinTime[i]) //从第i号板子左端到地面的最短时间
		leftMinTime[i] = MinTime(i, true);
	if(!rightMinTime[i])//从第i号板子右端到地面的最短时间 
		rightMinTime[i] = MinTime(i, false);
	nLeftTime += leftMinTime[i];
	nRightTime += rightMinTime[i];
	
	if( nLeftTime < nRightTime )
	return nLeftTime;
	return nRightTime;
}

int main() 
{
    
    
	int t, x, y; 
	scanf("%d",&t);
	for( int i = 0;i < t; i++ )
	{
    
    
		memset(leftMinTime, 0, sizeof(leftMinTime));
		memset(rightMinTime, 0, sizeof(rightMinTime));
		scanf("%d%d%d%d",&n, &x, &y, &maxHeight);//输入平台数,Jimmy的初始坐标及能下降的最大高度 
		platForms[0].Lx = x; 
		platForms[0].Rx = x;//Jimmy所在的平台长度为0 
		platForms[0].h = y;
		for( int j = 1; j <= n; j ++ )
	 	scanf("%d%d%d",&platForms[j].Lx,& platForms[j].Rx, & platForms[j].h);
		
		sort(platForms, platForms+n+1);//将平台按高度从大到小进行排序,即将Jimmy所在的长度为0的编号为0再依次编号 
		printf("%d\n", MinTime(0, true));//假设向左走从第i块板子到地面的最短时间 
	} 
	return 0;
}

Method two recursion

//递推 
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define MAX_N 1000
#define INFINITE 1000000
int t,n,x,y,maxHeight;
struct Platform{
    
    
	int Lx, Rx, h;
	bool operator < (const Platform & p) const {
    
    
		return h > p.h;
	}
};
Platform platforms[MAX_N + 10];
int leftMinTime[MAX_N + 10]; //各板子从左走最短时间
int rightMinTime[MAX_N + 10]; //各板子从右走最短时间

int main()
{
    
    
	scanf("%d",&t);
	while(t--) 
	{
    
    
		scanf("%d%d%d%d",&n, &x, &y, &maxHeight);
		platforms[0].Lx = x; 
		platforms[0].Rx = x; 
		platforms[0].h = y;
		for( int j = 1; j <= n; j ++ )
		scanf("%d%d%d",&platforms[j].Lx,& platforms[j].Rx,& platforms[j].h);
		sort(platforms,platforms+n+1);
		for( int i = n ; i >= 0; i-- ) 
		{
    
    
			int j;
			for( j = i + 1; j <= n ; ++ j ) {
    
     //找i的左端的下面那块板子
				if( platforms[i].Lx <= platforms[j].Rx && platforms[i].Lx >= platforms[j].Lx)
	                break;
			}
			if( j >n ) {
    
     //找不到
				if( platforms[i].h > maxHeight )	leftMinTime[i] = INFINITE;
				else	leftMinTime[i] = platforms[i].h;
			}
			else {
    
    
				int y = platforms[i].h - platforms[j].h;
				if( y > maxHeight) leftMinTime[i] = INFINITE;
				else leftMinTime[i] = y + min(leftMinTime[j]+platforms[i].Lx-platforms[j].Lx,
	 				rightMinTime[j]+platforms[j].Rx-platforms[i].Lx);
			}
			for( j = i + 1; j <= n ; ++ j ) {
    
     //找i的右端的下面那块板子
				if( platforms[i].Rx <= platforms[j].Rx&& platforms[i].Rx >= platforms[j].Lx)
					break;
			}
			if( j > n ) {
    
    
				if( platforms[i].h > maxHeight ) rightMinTime[i] = INFINITE;
				else rightMinTime[i] = platforms[i].h;
			}
			else {
    
    
				int y = platforms[i].h - platforms[j].h;
				if( y > maxHeight) rightMinTime[i] = INFINITE;
				else	rightMinTime[i] = y + min(leftMinTime[j]+platforms[i].Rx-platforms[j].Lx,
				rightMinTime[j]+platforms[j].Rx-platforms[i].Rx);
			}
		}
		printf("%d\n", min(leftMinTime[0],rightMinTime[0]));
	}
	return 0;
}

Algorithm analysis

After Jimmy jumps to a board, he has two choices, go left or go right. The time required to walk to the left and to the right is easy to calculate. If we can know the shortest time to reach the ground with the left end as the starting point and the shortest time to reach the ground with the right end as the starting point, then it is easy to choose whether to go left or right. Therefore, the whole problem is decomposed into two sub-problems, namely, the shortest time from the starting point to the ground at the left end of the first board below Jimmy's location, and the shortest time from the starting point to the ground at the right end. These two sub-problems are completely consistent with the original problem in form. Number the boards from top to bottom starting from 1 without repetition (the higher the board, the smaller the number, the number of boards with the same height, it does not matter which number is in the front), then, the variables related to the above two sub-questions are only The number of the board.

Let’s think that Jimmy’s starting position is a board numbered 0 and a length of 0. Let’s say LeftMinTime(k) represents the shortest time from the left end of the k board to the ground. RightMinTime(k) represents the shortest time from the right end of the k board to the ground. Then, the method to find the shortest time from the left end of the board k to the ground is as follows:

if (板子k左端正下方没有别的板子)
 {
	if(板子k的高度 h(k) 大于Max)
	LeftMinTime(k) = ∞;
	else LeftMinTime(k) = h(k);
}
else if( 板子k左端正下方的板子编号是m )
LeftMinTime(k) = h(k)-h(m) + min(LeftMinTime(m) + Lx(k)-Lx(m),RightMinTime(m) + Rx(m)-Lx(k));

Above, h(i) represents the height of board i, Lx(i) represents the abscissa of the left end of board i, and Rx(i) represents the abscissa of the right end of board i. Then h(k)-h(m) is of course the time required to jump from board k to board m, and Lx(k)-Lx(m) is to walk from the foothold of board m to the left end of board m Rx(m)-Lx(k) is the time required to walk from the foothold of board m to the right end. The process of seeking RightMinTime(k) is similar. Let's think that Jimmy's starting position is a board numbered 0 and length 0, so the whole problem is to require LeftMinTime(0). In the input data, the boards are not sorted by height, so the boards must be sorted first in the program.

Time complexity : a
total of n boards, the minimum time of each left and right ends are counted once o (n) o(n)o ( n ) To
find out which board is between a section of the board and the ground, you need to traverse the boardo (n) o(n)o ( n )
Total time complexityo (n 2) o(n^2)o ( n2)

Guess you like

Origin blog.csdn.net/m0_51354361/article/details/113524114