貪心例題

清風紫雪發表於2020-06-19

1.雷達裝置

題目連結:https://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.付賬問題

題目連結:https://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.乘積最大

題目連結:https://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;
}

 

相關文章