poj1661-help Jimmy(动态规划递归求解)

(来源于mooc郭炜老师的 程序设计与算法(二):算法基础  课程)(我只是个思路的搬运工,代码是我自己写的以供参考,不过本人不才这个代码提交到poj上超时了,我不知道怎么优化,所以这篇文章即是分享也是请教,希望大牛可以教教我怎么优化这个代码)

解题思路:

Jimmy跳到一块板子上可以向左走也可以向右走,走到左边或者右边这个时间我们是很容易计算的。

如果我们知道以左端为起点到达地面的最短时间,和以右端为起点到达地面的最短时间,那么我们就可以在向左走还是向右走两个选项中选择那个花费时间更少的。

这样我们就可以将整个问题分解为两个子问题:1.Jimmy所在位置下方第一块板子左端为起点到地面的最短时间   2.以右端为起点到地面的最短时间

这两个子问题在形式上和原问题一致。和子问题相关的变量就只有板子编号。

(懒得打字了,直接上图)

 下面是我自己写的代码(超时了):

#include <iostream>
#include <cmath>
using namespace std;
int N;
int Max;
struct banzi {//板子的信息
	int height;
	int left;
	int right;
} ban[1000];
int leftmintime(int k);
int rightmintime(int k);
void quicksort(struct banzi ban[], int Left, int Right);//将板子从高到低排序编号
int getlow(int k, bool L);//得到编号k板子下一块板子编号
int main() {
	int t;
	cin >> t;
	int x, y;
	while (t--) {
		scanf("%d%d%d%d", &N, &x, &y, &Max);
		ban[0].left = ban[0].right = x;
		ban[0].height = y;
		for (int i = 1; i <= N; i++)
			cin >> ban[i].left >> ban[i].right >> ban[i].height;
		quicksort(ban, 1, N);
		cout << leftmintime(0) << endl;
	}
}

int leftmintime(int k) {
	int m;
	m = getlow(k, true);
	if (m == N + 1) {
		if (ban[k].height <= Max)
			return ban[k].height;
		else
			return 999999;
	} else {
		return ban[k].height - ban[m].height +
		       min(leftmintime(m) + ban[k].left - ban[m].left, rightmintime(m) + ban[m].right - ban[k].left);
	}
}

int rightmintime(int k) {
	int n;
	n = getlow(k, false);
	if (n == N + 1) {
		if (ban[k].height <= Max)
			return ban[k].height;
		else
			return 999999;
	} else {
		return ban[k].height - ban[n].height +
		       min(leftmintime(n) + ban[k].right - ban[n].left, rightmintime(n) + ban[n].right - ban[k].right);
	}
}
void quicksort(struct banzi ban[], int Left, int Right) {
	if (Left >= Right)
		return;
	int i = Left, j = Right;
	int key = ban[Left].height;
	while (i < j) {
		while (ban[j].height <= key && i < j)
			j--;
		while (ban[i].height >= key && i < j)
			i++;
		if (i < j) {
			struct banzi t = ban[i];
			ban[i] = ban[j];
			ban[j] = t;
		}
	}
	struct banzi temp = ban[Left];
	ban[Left] = ban[i];
	ban[i] = temp;
	quicksort(ban, Left, i - 1);
	quicksort(ban, i + 1, Right);
}
int getlow(int k, bool L) {
	int i;
	if (L) {
		for (i = k + 1; i <= N; i++) {
			if (ban[i].left < ban[k].left && ban[i].right > ban[k].left)
				break;
		}
	} else {
		for (i = k + 1; i <= N; i++) {
			if (ban[i].left < ban[k].right && ban[i].right > ban[k].right)
				break;
		}
	}
	return i;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值