算法竞赛进阶指南——基本算法(贪心)

股票买卖

算法竞赛进阶指南——基本算法(贪心)_第1张图片
算法竞赛进阶指南——基本算法(贪心)_第2张图片
算法竞赛进阶指南——基本算法(贪心)_第3张图片
低买高卖

#include
using namespace std;
const int N = 1e5 + 10;
int a[N];
int n, res;

int main(){
    cin>>n;
    for(int i = 0; i < n; i++){
        cin>>a[i];
    }
    for(int i = 1; i < n; i++){
       if(a[i] > a[i - 1]){
           res += a[i] - a[i - 1];
       } 
    }
    cout<<res;
    return 0;
}

防晒

算法竞赛进阶指南——基本算法(贪心)_第4张图片
算法竞赛进阶指南——基本算法(贪心)_第5张图片
算法竞赛进阶指南——基本算法(贪心)_第6张图片
算法竞赛进阶指南——基本算法(贪心)_第7张图片

#include
#include
using namespace std;
const int N = 2510;
pair<int, int> a[N], b[N];
int c, l;
int ans;

//按照左端点降序排序
bool cmp(const pair<int, int> p, const pair<int, int> q){
    return p.first > q.first;
}

int main(){
    cin>>c>>l;
    int x, y;
    for(int i = 0; i < c; i++){
        cin>>x>>y;
        a[i] = make_pair(x, y);
    }
    sort(a, a + c, cmp);
    for(int i = 0; i < l; i++){
        cin>>x>>y;
        b[i] = make_pair(x, y);
    }
    sort(b, b + l, cmp);
    for(int i = 0; i < c; i++){
        for(int j = 0; j < l; j++){
            if(a[i].first <= b[j].first && a[i].second >= b[j].first && b[j].second){
                ans++;
                b[j].second--;
                break;
            }
        }
    }
    cout<<ans;
    return 0;
}

畜栏预定

算法竞赛进阶指南——基本算法(贪心)_第8张图片
算法竞赛进阶指南——基本算法(贪心)_第9张图片

#include
#include
#include
using namespace std;
const int N = 5e4 + 10;
pair<pair<int, int>, int> a[N]; //存储吃草时间和奶牛编号
int id[N]; //存储畜栏编号
int n;

//按照左端点升序排序
bool cmp(const pair<pair<int, int>, int> p, const pair<pair<int, int>, int> q){
    return p.first.first < q.first.first;
}

int main(){
    cin>>n;
    int x, y;
    for(int i = 1; i <= n; i++){
        cin>>x>>y;
        a[i] = make_pair(make_pair(x, y), i);
    }
    sort(a + 1, a + n + 1, cmp);
    //小根堆,存储右端点最小值和区间编号
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> h;
    for(int i = 1; i <= n; i++){
        //如果没有畜栏或者堆顶大于等于当前左端点,那么新建一个畜栏,不能一起吃草
        if(h.empty() || h.top().first >= a[i].first.first){
            pair<int, int> t = make_pair(a[i].first.second, h.size() + 1);
            //更新这头牛的畜栏编号
            id[a[i].second] = t.second;
            //存入这头牛
            h.push(t);
        }else{
            //有畜栏,且当前左端点小于等于堆顶,和堆顶在同一个畜栏中,则弹出堆顶,插入这头牛
            pair<int, int> t = h.top();
            h.pop();
            t.first = a[i].first.second;
            id[a[i].second] = t.second;
            h.push(t);
        }
    }
    cout<<h.size()<<endl;
    for(int i = 1; i <= n; i++){
        cout<<id[i]<<endl;
    }
    return 0;
}

雷达设备

算法竞赛进阶指南——基本算法(贪心)_第10张图片
算法竞赛进阶指南——基本算法(贪心)_第11张图片
算法竞赛进阶指南——基本算法(贪心)_第12张图片

//根据左端点排序
#include
#include
#include
using namespace std;
const int N = 1e3 + 10;
pair<double, double> a[N], b[N];
int n, d;
int res;

int main(){
    cin>>n>>d;
    double x, y;
    for(int i = 0; i < n; i++){
        cin>>x>>y;
        a[i] = make_pair(x, y);
    }
    for(int i = 0; i < n; i++){
        if(a[i].second > d){
            cout<<-1;
            return 0;
        }else{
            x = a[i].first, y = a[i].second;
            double z = sqrt(d * d - y * y);
            b[i] = make_pair(x - z, x + z);
        }
    }
    //按照左端点升序排序
    sort(b, b + n);
    double ed = -1e9;
    for(int i = 0; i < n; i++){
        if(b[i].first > ed){
            res++;
            ed = b[i].second;
        }else{
        	//要维护右端点最小值
            ed = min(ed, b[i].second);
        }
    }
    cout<<res;
    return 0;
}

//根据右端点排序
#include
#include
#include
using namespace std;
const int N = 1e3 + 10;
pair<double, double> a[N], b[N];
int n, d;
int res;

int main(){
    cin>>n>>d;
    double x, y;
    for(int i = 0; i < n; i++){
        cin>>x>>y;
        a[i] = make_pair(x, y);
    }
    for(int i = 0; i < n; i++){
        if(a[i].second > d){
            cout<<-1;
            return 0;
        }else{
            x = a[i].first, y = a[i].second;
            double z = sqrt(d * d - y * y);
            b[i] = make_pair(x + z, x - z);
        }
    }
    //按照右端点升序排序
    sort(b, b + n);
    double ed = -1e9;
    for(int i = 0; i < n; i++){
        if(b[i].second > ed){
            res++;
            ed = b[i].first;
        }
    }
    cout<<res;
    return 0;
}

国王游戏

算法竞赛进阶指南——基本算法(贪心)_第13张图片
算法竞赛进阶指南——基本算法(贪心)_第14张图片

#include
#include
using namespace std;
const int N = 1e4 + 10;
pair<int, int> res[N];
int n, ans;

//根据左右乘积升序排序
bool cmp(const pair<int, int> p, const pair<int, int> q){
    return p.first * p.second < q.first * q.second;
}

int main(){
    cin>>n;
    int x, y;
    for(int i = 0; i <= n; i++){
        cin>>x>>y;
        res[i] = make_pair(x, y);
    }
    sort(res + 1, res + n + 1, cmp);
    for(int i = 1; i <= n; i++){
        int ans1 = 1, ans2;
        for(int j = 0; j < i; j++){
            ans1 *= res[j].first;
        }
        ans2 = ans1 / res[i].second;
        ans = max(ans, ans2);
    }
    cout<<ans;
    return 0;
}

//高精度
#include
#include
#include

using namespace std;

int v, Max;  // v是a * b, Max里存最大的v
int n;
int A, B;  //最大的a 和 b(左手和右手)
int ans[40000001], len;  //len 为ans数组的长度

void mul(int x)  //高精度乘法 ,把所有的a乘起来
{
    for (int i = 1; i <= len; i++)
        ans[i] *= x;   // 先让每一位数都乘x

    for (int i = 1; i <= len + 15; i++) // 15是因为最多进9位,所以就多算几位保险 
    {
        ans[i + 1] += ans[i] / 10;  //进位
        ans[i] %= 10;
    }

    for (int i = len + 15; i >= len; i--)
    if (ans[i] != 0)
        len = i;    //计算乘之后的位数

    return; //到最后ans数组是倒序的,比如123在ans数组里排列就是321
}

void div(int x)  //高精度除法, 此时x = 所有的a相乘
{
    int cnt = 0;

    for (int i = len; i >= 1; i--)
    {
        cnt = cnt * 10 + ans[i];
        if (cnt < x)
        {
            ans[i] = 0;
            continue;
        }
        ans[i] = cnt / x;
        cnt %= x;
    }

    for (int i = len; i >= 1; i--) //求出除去前导0剩下的长度
    if (ans[i] != 0)  
    {
        len = i;
        break;
    }

    return;
}
int main()
{
    cin >> n;
    ans[1] = 1; len = 1;
    for (int i = 1; i <= n + 1; i++)
    {
        int a, b;
        cin >> a >> b;
        mul(a);     //先把所有的a乘到答案里
        v = a * b;
        if (v > Max && i != 1)  //找出 左手*右手 最大的人,且这个人不是国王
            Max = v, B = b, A = a;
    }
    div(A * B);  //做除法的时候再把最大的那个a除去,就相当于没乘最大的a
    if (ans[len] == 0)
        ans[len] = 1;  //最少为1 
    for (int i = len; i >= 1; i--)
        cout << ans[i];
    cout << endl;
    return 0;
}

给树染色

算法竞赛进阶指南——基本算法(贪心)_第15张图片
算法竞赛进阶指南——基本算法(贪心)_第16张图片
算法竞赛进阶指南——基本算法(贪心)_第17张图片

#include
using namespace std;
const int N = 1e3 + 10;
struct Node{
    int fa, cnt, sum;
    double avg;
}nodes[N];
int n, root;

int find(){
    int res = -1;
    double avg = 0;
    for(int i = 1; i <= n; i++){
        if(i != root && nodes[i].avg > avg){
            avg = nodes[i].avg;
            res = i;
        }
    }
    return res;
}

int main(){
    cin>>n>>root;
    int res = 0;
    for(int i = 1; i <= n; i++){
        //t是引用,不是副本,之后对t的修改会影响到nodes[i]
        auto &t = nodes[i];
        cin>>t.sum;
        t.cnt = 1;
        t.avg = t.sum;
        res += t.sum;
    }
    int x, y;
    for(int i = 0; i < n - 1; i++){
        cin>>x>>y;
        nodes[y].fa = x;
    }
    for(int i = 0; i < n - 1; i++){
        int u = find();
        int f = nodes[u].fa;
        res += nodes[u].sum * nodes[f].cnt;
        //删掉这个点
        nodes[u].avg = -1;
        for(int j = 1; j <= n; j++){
            if(nodes[j].fa == u){
                nodes[j].fa = f;
            }
        }
        nodes[f].sum += nodes[u].sum;
        nodes[f].cnt += nodes[u].cnt;
        nodes[f].avg = (double)nodes[f].sum / nodes[f].cnt;
    }
    cout<<res;
    return 0;
}

你可能感兴趣的:(算法竞赛进阶指南,算法,数据结构)