贪心例题

1.雷达设备

题目链接://www.acwing.com/problem/content/114/

解决思路:我们所要找到的是雷达的最小数目,因此我们需要对每个小岛进行大都分析

①求出能够到达他的海岸线的范围,通过d与y我们可以求出他的x轴上的覆盖范围,(l,r),然后按照区间的右端点排序。

②求出每个岛的覆盖范围后,我们需要找出最少的使用雷达的数量,如果当前区间包括下一点的区间范围,则直接跳过;如果当前区间不能包含下一个区间,则增加一个雷达数目,并且将雷达范围更新为下一个雷达的区间。

例如下图所示:只需要三个雷达即可

 

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=10101;
struct node
{
    double l,r;
    bool operator <(const node &t)const
    {
        return r<t.r;
    }
}s[N];
int main()
{
    int i,j,n,d,x,y;
    bool flag=false;
    scanf("%d%d",&n,&d);
    for(i=0;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        if(y>d)
            flag=true;
        else
        {
            double len=sqrt(d*d-y*y);
            s[i].l=x-len;s[i].r=x+len;//计算每个岛的区间
        }
    }
    if(flag==true)
    {
        puts("-1");
    }
    else
    {
        sort(s,s+n);//按照区间右端点排序
        int cnt=0;
        double nowl=-1e20;
        for(i=0;i<n;i++)
        {
            if(nowl<s[i].l)//判断当前取件是否有下一个区间的点
            {
                cnt++;
                nowl=s[i].r;//更新区间
            }
        }
        printf("%d\n",cnt);
    }
    return 0;
}

 

2.付账问题

题目链接://www.acwing.com/problem/content/1237/

解题思路:计算最小的方差,S是固定的,因此AVG也是固定的,只要每个人所掏的钱数越接近于AVG,那么方差就会越小

①首先如果每个人的钱数都超过AVG,那么方差就是0

②如果有的人可能钱包小于AVG,那么不够的钱应该分摊到那些钱包有剩余的人那里,因此,我们首先需要将每个人的钱进行从小到大排序,分别计算当前人数的平均值,看当前这个人的钱包是否足够,不够就掏出自己目前所有的钱,然后,到第二个人的时候需要掏的钱:(S-a[0])/(n-1),如果也不够,也是掏出自己目前所有的钱,到第三个人的时候需要掏出:(S-a[0]-a[1])/(n-2)依次类推,算出最小方差,进而算出最小标准差,再保留4为小数。

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=500010;
int n,a[N];
double s;

int main()
{
    int i,j;
    cin>>n>>s;
    for(i=0;i<n;i++)
        cin>>a[i];
    sort(a,a+n);
    double ans=0,avg=s/n;
    for(i=0;i<n;i++)
    {
        double cur=s/(n-i);
        if(a[i]<cur)
            cur=a[i];
        ans+=(cur-avg)*(cur-avg);
        s-=cur;
    }
    printf("%.4lf",sqrt(ans/n));
    return 0;
}

 

3.乘积最大

题目链接://www.acwing.com/problem/content/description/1241/

解题思路:双指针算法,根据K的奇偶分别计算

当K是偶数,结果非负,因为,如果负数是偶数个,负负得正,结果为非负;如果负数是奇数个,那就选偶数个绝对值最大的负数

k 如果是奇数个的话,
(1)所有的数字如果都是负数,那么选出来的结果也一定都是负数
(2)否则的话,则一定至少有 1个非负数, 那么我们将最大的数取出来, 此时要选的个数就是 k–,
# k– 是偶数,那么就又转化为 k– 是偶数的情况思考

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
int n,k;
const int mod=1000000009;
const int N=100010;
int a[N];
int main()
{
    int i,j;
    cin>>n>>k;
    for(i=0;i<n;i++)
        cin>>a[i];
    sort(a,a+n);
    ll res=1,l=0,r=n-1;
    int sign=1;
    if(k%2)
    {
        res=a[r--];
        k--;
        if(res<0)
            sign=-1;
    }
    while(k)
    {
        ll x=(ll)a[l]*a[l+1];
        ll y=(ll)a[r]*a[r-1];
        if(x*sign>y*sign)
        {
            res=x%mod*res%mod;
            l+=2;
        }
        else
        {
            res=y%mod*res%mod;
            r-=2;
        }
        k-=2;
    }
    printf("%lld",res);
    return 0;
}

 

Tags: