贪心算法

1.区间调度

问题描述:有n项工作,每项工作分别在si开始,ti结束。对每项工作,你都可以选择参加或不参加,但选择了参加某项工作就必须至始至终参加全程参与,即参与工作的时间段不能有重叠(即使开始的时间和结束的时间重叠都不行)。你的目标是参与尽可能多的工作,那么最多参与多少项工作?

限制条件:1<=n<=100000 1<=si<=ti<=10^9

输入 n=5 s={1,2,4,6,8} T={3,5,7,9,10}

输出 3

 

思路:选取结束时间最早的工作

//
// Created by 86157 on 2021/3/26.
//
#include<bits/stdc++.h>
using namespace std;
const int Max=10005;

pair<int,int> p[Max];
int main(){
    int n,cnt=0,t=0;
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>p[i].second>>p[i].first;//first 为结束时间 second 为开始时间
    sort(p,p+n);
    for(int i=0;i<n;i++){
        if(p[i].second>t){
            cnt++;
            t=p[i].first;//把结束时间与下一段开始时间进行比较
        }
    }
    cout<<cnt;

    return 0;
}

 

2.

题目描述

滨海公园旁边新铺了一条路,把这条路分成n段,依次编号为1…n。为了防止游客把垃圾扔到海里,war要在路上放一些垃圾桶🚮。政府提出了m个要求,每个要求包含三个整数l,r,k,表示路段l到r之间至少有k个垃圾桶 。垃圾桶放太多不仅浪费资源,也影响风景,所以每个路段至多可以放一个垃圾桶。为了环保♻️,war最少要放多少个垃圾桶才能满足要求?

输入描述

第一行为n(1≤n≤3∗104)(1≤n≤3*10^4)(1≤n≤3∗104),表示路段数。

第二行为m(1≤m≤5000)(1≤m≤5000)(1≤m≤5000),表示要求数。

下面m行,每行描述一条建议l,r,k,用一个空格分隔,(1≤l≤r≤3∗104,k≤r−l+1)(1≤l≤r≤3*10^4,k≤r-l+1)(1≤l≤r≤3∗104,k≤r−l+1)。

输出描述

输出只有一个数,为满足政府所有的要求,需要的垃圾桶的最少数量。

​

#include<bits/stdc++.h>
using namespace std;

struct node{
    int l;
    int r;
    int num;
}a[5010];
int v[30010]={0};

bool cmp(node a1,node a2){
    return a1.r<a2.r;
}

int main(){
    int n,m,cnt=0;
    cin>>n>>m;
    for(int i=0;i<m;i++)
        cin>>a[i].l>>a[i].r>>a[i].num;
    sort(a,a+m,cmp);//错误,数量为m而不是n 记住记住!!!

    for(int i=0;i<m;i++){
        int l1=a[i].l,r1=a[i].r,cnt1=0;
        for(int j=l1;j<=r1;j++){
            if(v[j]==1) cnt1++;
        }
        while(cnt1<a[i].num){
            if(v[r1]==0){
                v[r1]=1;
                cnt1++;
                cnt++;
            }
            r1--;
        }
    }
    cout<<cnt;
    return 0;
}

[点击并拖拽以移动]
​

3.

B : 看电影

Description

题目描述

终于可以随意出入校园啦!于是,n个人决定去看电影🎬。每个人都要先去A影院再去B影院。第i个人在A,BA,BA,B影院的观影时间分别为ai,bia_i,b_iai​,bi​。按照疫情防控要求,每个影院最多允许1人同时观影。那么怎样安排这n个人的观影顺序,能使所有人都在A,BA,BA,B影院观影完的总时间最少。

输入描述

第一行为n(0<n<1000)(0<n<1000)(0<n<1000),表示人数。

第二行n个数,第i个数为ai(1≤ai≤350)a_i(1≤a_i≤350)ai​(1≤ai​≤350),中间有空格。

第三行n个数,第i个数为bi(1≤bi≤350)b_i(1≤b_i≤350)bi​(1≤bi​≤350),中间有空格。

输出描述

输出只有一个数,为最少的总时间。

提示

贪心,可能需要了解Johnson法则

#include<bits/stdc++.h>
using namespace std;

struct node{
    int time;
    int index;
    int flag;//1代表b<a,0代表a<b
}p[1005];
bool cmp(node a,node b){
    return a.time<b.time;
}
int main(){
    int n,x[1005],y[1005],order[1005];
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>x[i];
    for(int i=0;i<n;i++)
        cin>>y[i];
    for(int i=0;i<n;i++){
        if(x[i]<=y[i]){
            p[i].time=x[i];
            p[i].flag=0;
            p[i].index=i;
        }
        else{
            p[i].time=y[i];
            p[i].flag=1;
            p[i].index=i;
        }
    }
    sort(p,p+n,cmp);
    int t=0,k=n-1;
    for(int i=0;i<n;i++){
        if(p[i].flag==0) order[t++]=p[i].index;//A影院
        if(p[i].flag==1) order[k--]=p[i].index;//B影院
    }

    int temp=x[order[0]],sum=x[order[0]];
    for(int i=1;i<n;i++){
        temp=temp+x[order[i]];
        sum=sum+y[order[i-1]];
        if(temp>sum) sum=temp;
    }
    sum=sum+y[order[n-1]];
    cout<<sum;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值