• 【算法】贪心


    1>不相交区间区间问题

    活动安排

    求不相交区间个数

    这里选择将r作为限制,以达到全局最优的目的

    策略:选择对后面影响小的

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int n;
    const int N=1003;
    struct node
    {
        int l,r;
        bool operator < (const node & o)
        { return r==o.r?l<o.l:r<o.r; }
    }d[N];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d%d",&d[i].l ,&d[i].r );
        sort(d+1,d+n+1);
        
        int cnt=1,nw=d[1].r ;
        for(int i=2;i<=n;i++)
            if(d[i].l >=nw) cnt++,nw=d[i].r ;
        
        printf("%d
    ",cnt);
        return 0;
    }

    2>区间选点问题

    尽量让每个点给多个区间使用,即尽量在重叠区域种树

    因为点的分布可能是:

    l 0 0 0 1 1 0 1 1 0 r

    所以只能把每个点的数记在每个点上,然后每个点只能种一次,所以用us记录

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int m,n;
    const int N=5003;
    struct node
    {
        int l,r,nd;
        bool operator < (const node & o)
        { return r==o.r?l<o.l:r<o.r; }
    }d[N];
    int tr[30003];
    bool us[30003];
    int lowbit(int x)
    { return x&(-x); }
    void add(int x)
    {
        for(;x<=m;x+=lowbit(x))
            tr[x]++;
    }
    int find(int l,int r)
    {
        int ans=0;
        for(;r;r-=lowbit(r))
            ans+=tr[r];
        for(;l;l-=lowbit(l))
            ans-=tr[l];
        return ans;
    }
    
    int main()
    {
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++) scanf("%d%d%d",&d[i].l ,&d[i].r ,&d[i].nd );
        sort(d+1,d+n+1);
        
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            int t=d[i].nd - find(d[i].l -1,d[i].r );
            if(t>0)
            {
                cnt+=t;
                while(t--) 
                {
                    while(us[d[i].r ]) d[i].r --;
                    add(d[i].r ),us[d[i].r ]=true;
                }
            }
        }
        
        printf("%d
    ",cnt);
        return 0;
    }

    3>区间覆盖问题

    思路:从左选到右,每次先选可能(即d[i].l<=tot_r), 再选最优(max(d[i].r),然后选了,

    为了减少选择时的遍历此时,我们将l严格排序,这样可以尽快找出可行解,

    而且当没有可以修改的量时,直接退出,表示无解

    #include<cstdio>
    #include<cstdlib>
    #include<cmath> 
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int t,n,l,w;
    double ww;
    const int N=15003;
    struct node
    {
        double l,r;
        bool operator < (const node & o) const
        { return l<o.l; }
    }d[N];
    
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&l,&w);
            ww=w*1.0/2,ww*=ww;
            double x,r;
            for(int i=1;i<=n;i++)
            {
                scanf("%lf%lf",&x,&r);
                if(r*2<=w) d[i].l =d[i].r =0;
                else
                {    
                    double t=sqrt(r*r-ww);
                    d[i].l =x-t,d[i].r =x+t;
                }
            }
            sort(d+1,d+n+1);
    //        for(int i=1;i<=n;i++)
    //            printf(" %lf %lf
    ",d[i].l ,d[i].r );
            
            int nw=1,cnt=0;
            double tot_r=0;
            while(nw<=n && tot_r<l)
            {
                double tt=tot_r;
                for(;d[nw].l<=tot_r && nw<=n;nw++)
                    if(d[nw].r >=tt)
                        tt=d[nw].r ;
                if(tt>tot_r) tot_r=tt,cnt++;
                else break;
            }
            
            if(tot_r<l) printf("-1
    ");
            else printf("%d
    ",cnt);
        }
        
        return 0;
    }

    4>[经典]加工生产调度

    先附上代码,思路即证明再说

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int n;
    const int N=1003;
    struct node
    {
        int a,b,c,xh;
        bool operator < (const node & o) const
        { return c<o.c; }
    }d[N];
    int ans[N],ta,tb;
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&d[i].a ),d[i].xh =i;
        for(int i=1;i<=n;i++)
            scanf("%d",&d[i].b ),d[i].c =min(d[i].a ,d[i].b );
        sort(d+1,d+n+1);
        
        int l=1,r=n;
        for(int i=1;i<=n;i++)
        {
            if(d[i].c ==d[i].a ) ans[l++]=i ;
            else ans[r--]=i ;
        }
        
        int rest=d[ans[1]].a ;
        tb=rest;
        for(int i=1;i<=n;i++)
        {
            int u=ans[i];
            tb+=max(0,d[u].a -rest)+d[u].b ;
            rest=d[u].b +max(rest-d[u].a ,0);
            ans[i]=d[ans[i]].xh ;
        } 
        printf("%d
    %d",tb,ans[1]);
        for(int i=2;i<=n;i++) printf(" %d",ans[i]);
        
        return 0;
    } 

     5>[均分纸牌]糖果传递

    看起来很难的样子

    实际上是道数学...不想证明了

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define int long long
    using namespace std;
    int n;
    const int N=1e6+3;
    int d[N],ave,ans;
    
    signed main()
    {
        scanf("%lld",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld",&d[i]),d[i]+=d[i-1];
        ave=d[n]/n;
        for(int i=1;i<n;i++)
            d[i]-=ave*i;
        
        sort(d+1,d+n);
        int pos=d[n/2];
        ans=max(pos,-pos); 
        for(int i=1;i<n;i++)
            ans+=abs(d[i]-pos);
        printf("%lld
    ",ans);
        return 0;
    } 

    补充一道极其像贪心的题,但是其实是有后效性的...

    石子合并

    以警示自己使用贪心前,能证明就证明

  • 相关阅读:
    期望最大化(Expectation Maximization)算法简介和Python代码实现
    LCE:一个结合了随机森林和XGBoost优势的新的集成方法
    90个Numpy的有用的代码片段
    5篇关于3D 卷积的最新论文推荐
    SQL 题目——必知必会
    Go 语言标准库之 context 包
    SQL 题目——入门篇
    Go 语言标准库之 encoding/json 包
    Git 命令入门
    MySQL 入门
  • 原文地址:https://www.cnblogs.com/xwww666666/p/11480896.html
Copyright © 2020-2023  润新知