zoukankan      html  css  js  c++  java
  • 贪心题集

    活动安排

    题目描述

    设有 个活动的集合 ,其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动 都有一个要求使用该资源的起始时间 和一个结束时间 ,且 。如果选择了活动 ,则它在时间区间 内占用资源。若区间 与区间 不相交,则称活动 与活动 是相容的。也就是说,当 或 时,活动 与活动 相容。选择出由互相兼容的活动组成的最大集合。

    思路

    按结束时间进行排序,先完成的先贪

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define int long long
    const int manx = 1e5;
    
    struct node{
        int l,r;
    }e[manx];
    int cmp(node a,node b){
         return a.r < b.r;
    }
    char obuf[1<<24], *O=obuf;
    void print(int x) {
        if(x > 9) print(x / 10);
        *O++ = x % 10 + '0';
    }
    int n;
     main(){
        cin >> n;
        for(int i = 1;i <= n; i++){
            cin>>e[i].l>>e[i].r;
        }
        sort(e+1,e+1+n,cmp);
        int top = 0,ans = 0;
        for(int i = 1;i <= n ; ++i){
            if(e[i].l >= top)
            {
                ans++;
                top = e[i].r;
            }
            continue;
        }
        print(ans),*O++ = '\n';
        fwrite(obuf, O-obuf, 1, stdout);
    } 
    

    种树

    题目描述

    某条街被划为 \(n\) 条路段,这 \(n\) 条路段依次编号为 \(1...n\) 。每个路段最多可以种一棵树。现在居民们给出了 \(h\) 组建议,每组建议包含三个整数 \(b,e,t\),表示居民希望在路段 \(b\)\(e\) 之间至少要种 \(t\) 棵树。这些建议所给路段的区间可以交叉。请问:如果要满足所有居民的建议,至少要种多少棵树。

    思路

    以后缀排序,把树种在末尾,每次更改时扫一遍已种的棵树,再在末尾种剩余的树,存在小的区间已经占有,大区间尾端被小区见更新,所以需要判断是否重新剑术

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define int long long
    const int manx = 1e6;
    
    
    char obuf[1<<24], *O=obuf;
    void print(int x) {
        if(x > 9) print(x / 10);
        *O++ = x % 10 + '0';
    }
    struct node{
        int l,r,s;
    }e[manx];
    int cmp(node a,node b){
        return a.r < b.r;//结束时间排序 
    }
    int n,m,v[manx];
    main(){
        cin >> n>>m;
        for(int i = 1;i <= m; i++){
            cin>>e[i].l >>e[i].r>>e[i].s;
        }
        sort(e+1,e+1+m,cmp);
        int top = 0,ans = 0;
        for(int i = 1;i <= m; i++){
            int js = 0;
            for(int j = e[i].l ; j <= e[i].r ;j ++){
                if(v[j] == 1)
                js++;
            }
            if(js < e[i].s){
                for(int j = e[i].r ; j >= e[i].l ; j--){
                    if(v[j] == 0)
                    {
                        v[j] = 1;//存在小区间已经占有,大区间尾端被小区见更新,所以需要判断是否重新剑术
       
                        if(++js == e[i].s) break;         
                    }
                }
            }
            else{
                continue;
            }
        }
        for(int i = 1;i <= n; i++){
            if(v[i] == 1)
            ans++;
        }
        print(ans),*O++ = '\n';
        fwrite(obuf, O-obuf, 1, stdout);
    } 
    

    排水装置

    题目描述

    \(L\) 米,宽 \(W\) 米的草坪里装有 \(n\) 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 \(\frac{W}{2}\) 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。

    请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?

    Picture1

    思路

    \[\sqrt{r^2 - {(\frac{W}{2})}^2} \]

    显然超过宽度 \(W\)的长度对答案有勾股定理的的范围贡献,因此可以将每个点都将其范围最大化,

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    using namespace std;
    const int manx = 1e6;
    double w;
    int n/*,n*/,t,l,js;
    double s ;
    double r ;
    struct node{
        double x,y;
    }e[manx];
    bool cmp(node a,node b){
        return a.x < b.x;
    }
    int main(){
        cin>>t;
        while(t--){
            cin>>n>>l>>w;
             js = 0;
            for(int i = 1;i <= n; i++){
                
                cin>>s>>r;
                if(r <= w/2) continue;
                js++;
                e[js].x = s - sqrt(r *r - (w/2)*(w/2));
                e[js].y = s + sqrt(r *r - w*w*0.25); 
            }
            sort(e+1,e+1+js,cmp);
            int ans = 0,flag = 1,i = 1;
            double top = 0;
            while(top < l){
                ans++;
                double s = top;
                for( ;e[i].x<=s&&i <= js; i++) top = max(top,e[i].y);
                if(s == top && s < l){
                    cout<<"-1"<<endl;
                    flag = 0;
                    break;
                }
            }
            if(flag) cout<<ans<<endl;
        }
        return 0;
    } 
    

    加工生产调度

    题目描述

    某工厂收到了 个产品的订单 \(n\),这 \(n\) 个产品分别在 A、B 两个车间加工,并且必须先在 A 车间加工后才可以到 B 车间加工。

    某个产品\(i\) 在 A,B 两车间加工的时间分别为 \(A_i\) \(B_i\)。怎样安排这 个产品的加工顺序,才能使总的加工时间最短。

    这里所说的加工时间是指:从开始加工第一个产品到最后所有的产品都已在 A,B 两车间加工完毕的时间。

    思路

    对于时间划分来说,为了达到目标,尽可能的让\(A,B\) 的休息时间尽量的少,那么将其划分为每个决策,每个决策都保证 \(A,B\) 的时间最小,因此可得贪心

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    const int manx = 1e5 + 10;
    struct node{
        int s,id,iid;
    }m[manx];
    int cmp(node a,node b){
        return a.s < b.s;
    }
    int n,a[manx],x[manx],y[manx];
    int main(){
        cin >> n;
        for(int i = 1;i <= n; i++){
            cin>>x[i];
        }
        for(int i = 1;i <= n; i ++){
            cin>>y[i];
        }
        for(int i = 1;i <= n; i++){
            m[i].s = min(x[i],y[i]);
            //cout<<m[i].s<<endl;
            if(x[i] == m[i].s) m[i].id = 0;
            else m[i].id = 1;
            m[i].iid = i;
        }
        sort(m+1,m+1+n,cmp);
        //for(int i = 1;i <= n; i++) cout<<m[i].s <<" ";
        int top = 0,till = n + 1;
        for(int i = 1;i <= n; i++){
            if(m[i].id == 0){
                a[++top] = m[i].iid; 
            } 
            if(m[i].id == 1){
                a[--till] = m[i].iid;
            }
        }
        int k = 0,t = 0;
        for(int i = 1;i<=n; i++){
            k+=x[a[i]];
            //cout<<k<<" "<<i<<endl;
            if(t<k) t = k;
            t += y[a[i]];
            //cout<<t<<" "<<i<<endl;
        }
        cout<<t<<endl;
        for(int i = 1;i <= n; i++) cout<<a[i]<<" ";
    }
    

    5.智力大冲浪

    题目描述

    小伟报名参加中央电视台的智力大冲浪节目。本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者 \(m\) 元。先不要太高兴!因为这些钱还不一定都是你的?!接下来主持人宣布了比赛规则:

    首先,比赛时间分为 \(n\) 个时段,它又给出了很多小游戏,每个小游戏都必须在规定期限 \(t_i\) 前完成。如果一个游戏没能在规定期限前完成,则要从奖励费 \(m\) 元中扣去一部分钱 \(w_i\)\(w_i\) 为自然数,不同的游戏扣去的钱是不一样的。当然,每个游戏本身都很简单,保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。主持人只是想考考每个参赛者如何安排组织自己做游戏的顺序。作为参赛者,小伟很想赢得冠军,当然更想赢取最多的钱!注意:比赛绝对不会让参赛者赔钱!

    思路

    显然是先做扣钱多的,其次是少的,在扣钱多的同一时间里,尽量的让大时间往后去,这就是贪心的思路

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define int long long
    const int manx = 1e6;
    
    struct node{
        int tim,m;
    }e[manx];
    int cmp(node a,node b){
        if(a.m == b.m)
        return a.tim > b.tim;
        return a.m > b.m;
    }
    int n,m,vis[manx],s[manx];
     main(){
        cin>>m>>n;
        for(int i = 1;i <= n; i++){
            cin>>e[i].tim;
        }
        for(int i = 1;i <= n; i++){
            cin>>e[i].m;
        }
        sort(e+1,e+1+n,cmp);
        for(int i = 1;i <= n; i++){
            while(vis[e[i].tim]) e[i].tim--;
            if(e[i].tim) vis[e[i].tim] = 1;
            else m -= e[i].m ;
        }
        cout<<m<<endl;
        
    }
    
  • 相关阅读:
    sci会议和sci期刊区别是什么
    微信小程序保存图片到相册
    详解python3如何调用c语言代码
    微信小程序的跳转navigateTo()和redirectTo()用法和区别
    python+opencv图像变换的两种方法cv2.warpAffine和cv2.warpPerspective
    微信小程序
    微信小程序不同机型的兼容布局解决
    cv2.warpAffine 参数详解
    np.vstack()和np.hstack()
    numpy.linalg.svd函数
  • 原文地址:https://www.cnblogs.com/lToZvTe/p/14146586.html
Copyright © 2011-2022 走看看