ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

贪心算法:推公式 耍杂技的牛

2022-07-20 20:02:38  阅读:190  来源: 互联网

标签:include 杂技 max 交换 si wi 算法 奶牛 贪心


C++

AcWing 125. 耍杂技的牛

/*
题目描述:
	Acwing 125. 耍杂技的牛:
	农民约翰的 N 头奶牛(编号为 1..N)计划逃跑并加入马戏团,为此它们决定练习表演杂技。
	奶牛们不是非常有创意,只提出了一个杂技表演:
	叠罗汉,表演时,奶牛们站在彼此的身上,形成一个高高的垂直堆叠。
	奶牛们正在试图找到自己在这个堆叠中应该所处的位置顺序。
	这 N 头奶牛中的每一头都有着自己的重量 Wi 以及自己的强壮程度 Si。
	一头牛支撑不住的可能性取决于它头上所有牛的总重量(不包括它自己)减去它的身体强壮程度的值,现在称该数值为风险值,风险值越大,这只牛撑不住的可能性越高。
	您的任务是确定奶牛的排序,使得所有奶牛的风险值中的最大值尽可能的小。

	输入格式:
	第一行输入整数 N,表示奶牛数量。
	接下来 N 行,每行输入两个整数,表示牛的重量和强壮程度,第 i 行表示第 i 头牛的重量 Wi 以及它的强壮程度 Si。

	输出格式:
	输出一个整数,表示最大风险值的最小可能值。

	数据范围:
	1 ≤ N ≤ 50000,
	1 ≤ Wi ≤ 10,000,
	1 ≤ Si ≤ 1,000,000,000

解题思路:
	对于本题,乍一看基本没什么明显的思路,因此,我们从交换 i 和 i + 1 牛的位置入手,查看什么时候交换 i 和 i + 1 牛的位置,可以使得其对结果更好。

	为什么选择 i 和 i + 1 ? 
		因为 交换 i 和 i + 1头牛的位置,对其他位置的牛危险值的计算没有影响,他**只会影响** i 和 i + 1 头牛风险值的大小。
		那么,我们只需要通过查看交换时候风险值是否变大,来决定是否需要交换。

	公式推导部分:
		首先我们假设当前顺序奶牛们的重量为 w1, ..., wn, 强壮程度 s1, ..., sn,方便比较假设 x = sum(w1, ..., w(i-1))
		可得 **交换前风险值**
			第 i 头奶牛: 		x - si
			第 i + 1 头奶牛: 	x + wi - s(i+1)
		可得 **交换后风险值**
			第 i 头奶牛: 		x - s(i+1)
			第 i + 1 头奶牛: 	x + w(i+1) - s(i)
		需要交换的情况:
			max(x - si, x + wi - s(i+1)) > max(x - s(i+1), x + w(i+1) - s(i))
		不需要交换的情况
			max(x - si, x + wi - s(i+1)) < max(x - s(i+1), x + w(i+1) - s(i))
		也就是我们需要选择 i 和 i + 1 头奶牛 max 风险值最小的那一个。我们以不需要交换情况为基础进行推导
		该问题可以选择的推导思路,首先判断 x - si 和 x + wi - s(i+1)的大小
		1. (x - si) < (x + wi - s(i+1)) 即为 s(i+1) - s(i) < w(i)
			max(x - si, x + wi - s(i+1)) = x + wi - s(i+1) < max(x - s(i+1), x + w(i+1) - s(i))
			因为 x + wi - s(i+1) >= x - s(i+1) 显然成立,
			因此不等式成立条件为
				x + wi - s(i+1) < x + w(i+1) - s(i)
			即为:
				wi + si < w(i+1) + s(i+1)
		2. (x - si) > (x + wi - s(i+1)) 即为 s(i+1) - s(i) > w(i)
			max(x - si, x + wi - s(i+1)) = x - si < max(x - s(i+1), x + w(i+1) - s(i))
			因为 x - si <= x + w(i+1) - s(i)) 显然成立,
			因此等式恒成立。
		
		讨论一可以得之,不等式成立条件为 s(i+1) - s(i) < w(i) && wi + si < w(i+1) + s(i+1) 
		讨论二可以得之,不等式成立条件为 s(i+1) - s(i) > w(i) && True,然而 s(i+1) - s(i) > w(i) 包含了 wi + si < w(i+1) + s(i+1) 

		因此,不等式成立条件为 wi + si < w(i+1) + s(i+1)。
		
		即为 wi + si < w(i+1) + s(i+1) 不需要交换 i, i + 1
			wi + si > w(i+1) + s(i+1) 需要交换 i, i + 1
			wi + si < w(i+1) + s(i+1) 可以交换 i, i + 1,也可以不交换。

		目前为止,我们只是推导出了 i 和 i + 1 的交换特性,该特性是否具有传递性呢? 
			**答案是具有的,因为 wi + si < w(i+1) + s(i+1) 本身只是和自身属性相关,具有传递性。**

			
	综上证明完毕,排序条件为 wi + si < w(i+1) + s(i+1)
 */
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>

using namespace std;

typedef pair<int, int> PII;
typedef long long LL;

const int N = 50010;
PII a[N];
int n;

bool cmp(const PII &t1, const PII &t2) {
	return t1.first + t1.second <= t2.first + t2.second;
}

LL solution() {
	LL res = -1e15;
	LL pre_weight_sum = 0;

	sort(a + 1, a + n + 1, cmp);

	for (int i = 1; i <= n; i ++ ) {
		res = max(res, pre_weight_sum - a[i].second);
		pre_weight_sum += a[i].first;
	}

	return res;
}


int main()
{
	// input
	scanf("%d", &n);
	for (int i = 1; i <= n; i ++ ) {
		scanf("%d%d", &a[i].first, &a[i].second);
	}

	LL res = solution();


	printf("%d\n", res);

	return 0;
}



标签:include,杂技,max,交换,si,wi,算法,奶牛,贪心
来源: https://www.cnblogs.com/lucky-light/p/16499617.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有