贪心算法

当一个问题具有最优子结构性质时,可以使用动态规划法求解,但有时候使用贪心算法更简单,更直接而且解决问题的效率很高。 当一个问题具有最优子结构性质时,可以使用动态规划法求解,但有时候使用贪心算法更简单,更直接而且解决问题的效率很高。
贪心算法总是做出在当前看来最好的选择,也就是说贪心算法并不从整体最优考虑,它所做出的选择只是在某种意义上的局部最优选择,当然最终希望贪心算法得到的最终结果也是最优的。 例如前面动态规划算法中的硬币问题就可以用贪心算法来解决,从算法名字上来看,贪心算法总是做出在当前看来最好的选择,也就是说贪心算法并不从整体最优考虑,它所做出的选择只是在某种意义上的局部最优选择,当然最终希望贪心算法得到的最终结果也是最优的。
虽然贪心算法不能对所有问题都得到整体最优解,但是对于很多问题它能够产生整体最优解,或者是趋近于最优解。 虽然贪心算法不能对所有问题都得到整体最优解,但是对于很多问题它能够产生整体最优解,或者是趋近于最优解。

硬币问题

1,3,5分的硬币,现在给定一个价值c:11,问组成价值c需要的最少的硬币的数量???
 

int main()
{
	int arr[] = { 5,3,1 };
	int length = sizeof(arr) / sizeof(arr[0]);
	int c = 11;

	int idx = 0;  // 5 3 1
	int cnt = 0; // 记录硬币的个数
	while (c > 0) {
		if (c >= arr[idx]) {
			c -= arr[idx];
			cnt++;
		}
		else {
			idx++;
		}
	}

	cout << cnt << endl;

	return 0;
}

部分背包问题

部分背包问题,有n个物体,第i个物体的重量为wi,价值为vi。在总重量不超过C的情况下让总价值尽量高。
每一个物体都可以只取走一部分,价值和重量按比例计算。求最大总价值。

struct Product {
	double getPrice()const {
		return v * 1.0 / w;
	}
	bool operator>(const Product &p) const {
		return getPrice() > p.getPrice();
	}
	int id; // 物品的id
	int w; // 物品的重量
	int v; // 物品的价值
};
int main()
{
	int w[] = { 8,6,4,2,5 };
	int v[] = { 6,4,7,8,6 };
	const int n = sizeof(w) / sizeof(w[0]);
	int c = 12;
	int x[n] = { 0 };

	Product pros[n];
	for (int i = 0; i < n; ++i) {
		pros[i].id = i;
		pros[i].w = w[i];
		pros[i].v = v[i];
	}

	// 按物品的性价比降序排列
	sort(pros, pros + n, [](const Product &p1, const Product &p2)->bool {return p1 > p2; });

	// 按性价比高的往背包里面放(只考虑局部的最优解)
	double bestv = 0.0; // 记录背包的最大价值
	for (int i = 0; i < n; ++i) {
		if (pros[i].w <= c) { // 说明第i个物品可以装入背包
			bestv += pros[i].v;
			c -= pros[i].w;
		}
		else { // 说明第i个物品无法全部装入背包,按剩余容量的比例装入物品的一部分
			bestv = bestv + pros[i].v*(c*1.0 / pros[i].w);
			x[pros[i].id] = 1;
			break;
		}

		x[pros[i].id] = 1;
	}

	cout << "bestv:" << bestv << endl;
	for (int v : x) {
		cout << v << " ";
	}
	cout << endl;

	return 0;
}

柜台提供服务

m个柜台提供服务,每个柜台给一个用户提供服务的时间是t(用数组表示每一个柜台提供服务的时间),
问怎么排列,使得柜台给所有用户提供服务的时间最少?

struct Counter {  // 描述柜台
	bool operator<(const Counter &counter) const {
		return time < counter.time;
	}
	int id; // 柜台id
	int time; // 柜台提供服务所花费的时间
};
int main()
{
	int arr[] = { 3,2,4 }; // 每一个柜台提供服务的时间
	const int m = sizeof(arr) / sizeof(arr[0]); // 柜台的数量
	int n = 15; // 办理业务的人数

	// 定义柜台信息数组,初始化柜台id和time
	Counter cons[m];
	for (int i = 0; i < m; ++i) {
		cons[i].id = i;
		cons[i].time = arr[i];
	}

	// 按照柜台提供服务的时间升序排列
	sort(cons, cons + m);

	int mintime = 0; // 记录给所有用户提供服务的最少时间
	int x[m] = { 0 }; // 记录每一个柜台安排的用户数量

	for (int i = 0; i < n; ++i) {
		// 先计算把i用户放在0号柜台的时间
		int time = cons[0].time * (x[0] + 1);   //   1 5      5 1
		// 再遍历其它的柜台,看是否可以得到更少的花费时间
		int j = 1;
		for (; j < m; ++j) {
			int t = cons[j].time * (x[j] + 1);
			if (t <= time) {  // 放在其它柜台处理时间总体更快,直接放入j柜台
				x[j]++;
				// 新添加了一个人,整体花费的时间有可能变得更长了,更新mintime
				if (t > mintime) {
					mintime = t;
				}
				break;
			}
		}
		// 最终还是放在0号柜台花费时间最少
		if (j == m) {
			x[0]++;
			// 新添加了一个人,整体花费的时间有可能变得更长了,更新mintime
			mintime = cons[0].time * x[0];
		}
	}

	cout << mintime << endl;
	for (int i = 0; i < m; ++i) {
		cout << arr[cons[i].id] << " : " << x[i] << endl;
	}

	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值