码迷,mamicode.com
首页 > 其他好文 > 详细

贪心题集

时间:2020-12-21 12:12:45      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:使用   选择   必须   中心   continue   algo   play   更新   而在   

活动安排

题目描述

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

思路

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

代码

#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}\) 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。

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

技术图片

思路

\[\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;
    
}

贪心题集

标签:使用   选择   必须   中心   continue   algo   play   更新   而在   

原文地址:https://www.cnblogs.com/lToZvTe/p/14146586.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!