天天快乐编程集训队2021暑假训练-0802-贪心题解

本次训练内容为贪心,也是普及组初赛非常喜欢考察的内容,大家务必要搞懂这个算法。
贪心就是不考虑整体情况,只取到达下一阶段哪个最优,即取局部最优解。和动态规划全局最优解不同
贪心的证明非常复杂(一般用数学归纳法、反证法等证明)。

1.6965 最优服务次序问题

我们用T(i)表示第i个顾客的等待时间,t(i)表示第i个顾客的服务时间
第一个顾客要等T(1)时间,为0
第二个同学要等T(2)时间,为t(1)
第三个同学要等T(3)时间,为t(1)+t(2)
...
第三个同学要等T(n)时间,为t(1)+t(2)+...+t(n-1)
等待总时间为 T=(n-1)*t(1)+(n-2)*t2+...+1*t(n-1)
要想让T最小,系数已经确定,那么我们只需要让t(1)、t(2)依次变大即T最小

#include<bits/stdc++.h>
using namespace std;
int a[100005];
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a,a+n);
    double sum=0;
    for(int i=0;i<n;i++)
    {
        sum+=a[i]*1LL*(n-i-1);
    }
    printf("%.2f
",sum/n);
    return 0;
}

2.6923 tencent's 商店

对应为1004 渊子赛马,我们需要让其正好能够买到,注意不要下标越界

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N], b[N];
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    for (int i = 0; i < m; i++)
        cin >> b[i];
    sort(a, a + n);
    sort(b, b + m);
    int i = n-1, j = m-1, ans = 0;
    while (i>=0 && j>=0)
    {
        if (a[i] >= b[j])
        {
            ans++;
            i--;
        }
        j--;
    }
    cout << ans << "
";
}

3.5594 区间问题

按照右端点排序,能先做完的先做,记录一下结束时间,判断下次是否可以做

#include<bits/stdc++.h>
using namespace std;
struct T{int l,r;}a[100005];
bool cmp(T a,T b){return a.r<b.r;}
int main()
{
	int n;
	while(cin>>n)
	{
		for(int i=0;i<n;i++)cin>>a[i].l;
		for(int i=0;i<n;i++)cin>>a[i].r;
		sort(a,a+n,cmp);
		int num=0,R=-1;
		for(int i=0;i<n;i++)
		{
			//可以做,就选择
			if(R<a[i].l)num++,R=a[i].r; 
		}
		cout<<num<<"
";
	}
	return 0;
}

4.2668 Lecture Halls (会议安排)

与上一题不同,不是不能做了就开间会议室,你新开的会议室接下来还可能要使用
可以把左右端点分别排序去考虑

5.5625 Kannyi爱种树

为区间覆盖问题,需要考虑分离、相交和包含,属于1532 校门外的树加强版

6.4879 积木大赛

如果当前的比现在的高,那么说明当前需要多盖两个的差;比现在的矮,说明选择的区间要截断,而且之前已经把当前的盖过了。所以只和前一个有关。

大佬您太强了,还请多多指教哎
原文地址:https://www.cnblogs.com/BobHuang/p/15088734.html