从7-1 汽车加油问题看贪心算法

贪心算法算是比较简单的算法,他需要包含两种性质,一种是贪心选择性质,另外一种是最优子结构性质
百度上的定义

在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择

解题角度

对于初学者而言,我觉得题目可以从以下角度入手:

  1. 是否能给输入按照一定标准排序
  2. 后面的解决办法是否跟前面有关即为,( d i s t a n c e [ i + 1 ] = d i s t a n c e [ i ] distance[i+1]=distance[i] distance[i+1]=distance[i])
  3. 求解顺序是否是从前往后,或者具有一定顺序。

7-1 汽车加油问题

题目来源:王晓东《算法设计与分析》

一辆汽车加满油后可行驶n公里。旅途中有若干个加油站。设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少

输入格式:

第一行有 2 个正整数n和 k(k<=1000 ),
表示汽车加满油后可行驶n公里,且旅途中有 k个加油站。
第二行有 k+1 个整数,表示第 k 个加油站与第k-1 个加油站之间的距离。
为什么会有k+1个数字呢?
ans:因为从起始站开始到终点共有n+1条线段
第 0 个加油站表示出发地,汽车已加满油。
第 k+1 个加油站表示目的地。

输出格式:

输出最少加油次数。如果无法到达目的地,则输出“No Solution!”
所以他有两种输出方式

输入样例:

7 7
1 2 3 4 5 1 6 6

输出样例:

4

完整代码如下

#include<bits/stdc++.h>
using namespace std;
#define MAXSIZE 1010
int dist[MAXSIZE] = { 0 };
int main() {
	int numIn = 0;
	int maxWalk = 0;
	int timesPickUp = 0;
	cin >> maxWalk >> numIn;
	int tem = maxWalk;
	//在起点的时候加满油了,这里初值一定要赋予。
	for (int i = 0; i <= numIn; i++) {
		cin >> dist[i];
	}
	for (int i = 0; i < numIn; i++) {
		tem -= dist[i];
		if (tem <= dist[i + 1] && tem + maxWalk >= dist[i + 1]) {
			//cout << i << " " << dist[i + 1] << " " << tem << endl;
			tem += maxWalk;
			timesPickUp++;
		}
		else if (tem + maxWalk < dist[i + 1]) {
			cout << "No Solution!";
			return 0;
		}
		else {
			if (tem < 0) {
				cout << "No Solution!";
				return 0;
			}
		}
	}
	//cout << endl;
	cout << timesPickUp;
	return 0;
}

贪心策略

这里的话,我主要考虑的是选取当我在i站的时候,考虑我能不能走到下一站,即为考虑i+1到i站的距离,所以这里会出现如下逻辑判断表达式

if (tem <= dist[i + 1] && tem + maxWalk >= dist[i + 1]) {
			//判断是否能够到达下一站,tem是剩余的油量能走的公里数,
			//maxWalk为加满油之后能走的公里数
			//而且这种情况是是在i站的时候发现剩余不够,
			//然后在i站加油之后能够顺利到达i+1站
			tem += maxWalk;
			timesPickUp++;
		}
		else if (tem + maxWalk < dist[i + 1]) {	
			//而且这种情况是是在i站的时候发现剩余不够,
			//然后在i站加油之后能够不能顺利到达i+1站
			cout << "No Solution!";
			return 0;
		}
		else {
			if (tem < 0) {
			//剩余油量不能到达
				cout << "No Solution!";
				return 0;
			}

容易错误的点

赋初值

	int tem = maxWalk;
	//在起点的时候加满油了,这里初值一定要赋予。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值