动态规划(二) Help Jimmy || 滑雪


例 Help Jimmy

题目链接:点击打开链接

解题思路



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));
}

代码实现:

/*
POJ1661 Help Himmy
这样效率太低了,一早上没看几个题
代码要是不是特别好看懂,先把伪代码写出来就比较好懂了

分析:
将板子由高到低按从0到n编号,起始点的为0
不妨认为Jimmy开始的位置是一个编号为0,长度为0的板子
设LeftMinTime(k)表示从k号板子左端到地面的最短时间
RightMinTime(k)表示从k号板子右端到地面的最短时间
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));
}
*/
#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;//Lx表示做边界横坐标,Rx表示右边界横坐标,h表示高度 
	bool operator < (const Platform & p2) const {//符号重载,sort的时候能按h从高到低排 
		return h > p2.h;
	}
};
Platform platForms[MAX_N + 10];//平台 
int leftMinTime[MAX_N + 10];//走左边的最小时间 
int rightMinTime[MAX_N + 10];//走右边的最小时间 
int L[MAX_N + 10];//
//l表示现在这块板的编号,越在上面的编号越小,bleft表示是否向左边走 
//因为这题分为向左和向右两种情况 
int MinTime(int l, bool bLeft)//l表示现在这块板的编号,越在上面的编号越小,bleft表示是否向左边走 
{
	//初始化x和y坐标,如果是去左边,就走到左边边上,如果去右边,就走到右边边上 
	int y = platForms[l].h;
	int x;
	//如果是去左边,就走到左边边上,如果去右边,就走到右边边上
	if (bLeft)
		x = platForms[l].Lx;
	else
		x = platForms[l].Rx;
	int i;
	for (i = l + 1; i <= n; i++) {//找到现在这块板下面的那块板 
		if (platForms[i].Lx <= x && platForms[i].Rx >= x)//判断从当前条能跳到的小一块板子上 
			break;
	}
	if (i <= n) {// 板子k左端正下方有别的板
		if (y - platForms[i].h > maxHeight)// 跳到这块平台的高度如果大于Max
			return INFINITE;//返回无限大 
	}
	else {// 板子k左端正下方没有别的板
		if (y > maxHeight)//板子k的高度 h(k) 大于Max
			return INFINITE;//返回无限大 
		else
			return y;//如果可以直接跳下,就输出y 
	}
	int nLeftTime = y - platForms[i].h + x - platForms[i].Lx;//现在平台与下一块平台的高度差以及下一块平台左边界的距离 
	int nRightTime = y - platForms[i].h + platForms[i].Rx - x;//现在平台与下一块平台的高度差以及下一块平台右边界的距离 
	if (leftMinTime[i] == -1) //等于-1表示我初始化过 ,如果还可以向左我们就向左 
		leftMinTime[i] = MinTime(i, true);//向左进入子问题 
	if (L[i] == -1)//等于-1表示我初始化过 ,如果还可以向右我们就向右 
		L[i] = MinTime(i, false);//像右进入子问题 
	nLeftTime += leftMinTime[i];//左边固定花费的时间加上下一场左边这样的时间 
	nRightTime += L[i];//右边固定花费的时间加上下一场右边这样的时间 
	//返回左边和右边走中值小的那一个 
	if (nLeftTime < nRightTime)
		return nLeftTime;
	return nRightTime;
}

int main() {
	int t;
	cin>>t;//读入t组数据 
	for (int i = 0; i < t; i++) {//对每组数据进行操作 
		memset(leftMinTime, -1, sizeof(leftMinTime));//初始化leftMinTime 
		memset(L, -1, sizeof(rightMinTime));//初始化L 
		cin>>n>>x>>y>>maxHeight;//读入数据 
		platForms[0].Lx = x; platForms[0].Rx = x;
		platForms[0].h = y;//起始点初始化 
		for (int j = 1; j <= n; j++)//读入平台信息 
			cin>>platForms[j].Lx>>platForms[j].Rx>>platForms[j].h;
		sort(platForms, platForms + n + 1);//对平台由高到低排序 
		cout<< MinTime(0, true);//MinTime()方法求下平台的最小时间 
	}
	return 0;
}

例 滑雪






代码实现:

扫描二维码关注公众号,回复: 1574829 查看本文章
#include<iostream>  
using namespace std;
const int Max = 105;

int row, col;
int map[Max][Max];                           //  记录图各点的高度。  
int dp[Max][Max];                            //  记录以各点为起点的最长下降路径的长度。  

int dfs(int r, int c)
{
	if (dp[r][c] != 0)
		return dp[r][c];      //  若dp[r][c]不为0,则表示它已被访问。  
	int max = 1;
	if (r + 1 <= row && map[r][c] > map[r + 1][c])
	{
		int len = dfs(r + 1, c) + 1;
		if (len > max)
			max = len;
	}
	if (r - 1 >= 1 && map[r][c] > map[r - 1][c])
	{
		int len = dfs(r - 1, c) + 1;
		if (len > max)
			max = len;
	}
	if (c + 1 <= col && map[r][c] > map[r][c + 1])
	{
		int len = dfs(r, c + 1) + 1;
		if (len > max)
			max = len;
	}
	if (c - 1 >= 1 && map[r][c] > map[r][c - 1])
	{
		int len = dfs(r, c - 1) + 1;
		if (len > max)
			max = len;
	}
	return map[r][c] = max;
}

int main()
{
	int i, j;
	cin >> row >> col;
	for (i = 1; i <= row; i++)
	for (j = 1; j <= col; j++)
		cin >> map[i][j];
	int ans = 0;
	memset(dp, 0, sizeof(dp));//给dp[][]全部初始化为0
	for (i = 1; i <= row; i++)
	for (j = 1; j <= col; j++)
	{
		dp[i][j] = dfs(i, j);  //  用记忆化搜索求出dp[i][j],同时也求出了其路径上的dp[x][y]。  
		if (dp[i][j] > ans)
			ans = dp[i][j];
	}
	cout << ans << endl;
	return 0;
}
参考资料: 动态规划3--Help Jimmy

滑雪问题

猜你喜欢

转载自blog.csdn.net/qq_42020563/article/details/80644017