YBTOJ 1.2贪心算法

A.奶牛晒衣服

image
image

很容易想到一个贪心思路:每次把烘干机会给当前湿度最大的衣服
我们假设有一次没烘干当前湿度最大的衣服
因为总时间取决于湿度最大的衣服
所以最后湿度最大的衣服湿度一定会更大点
那么要么总时间不变 要么会变长
一定不会更优
注意这题 \(n \le 5 * 10^5\) 需要采用 \(O(nlogn)\) 的大根堆

点击查看代码
#include <bits/stdc++.h>
using namespace std;

const int N = 5e5 + 0721;
int h[N];
int n, a, b, ans;
priority_queue<int, vector<int>, less<int> > q;

int main() {
    scanf("%d%d%d", &n, &a, &b);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &h[i]);
        q.push(h[i]);
    }

    while (1) {
        int now = q.top();
        q.pop();
        if (now <= ans * a)
            break;
        ++ans;
        now -= b;
        q.push(now);
    }

    printf("%d", ans);

    return 0;
}

B.雷达装置

image
image

首先二维不是很好考虑 思考能不能把信息全转化到 \(x\) 轴上
发现当 \(d\) 固定的时候 对于一个点 能覆盖到它的雷达是 \(x\) 轴上一段连续区间
我们考虑将点都转化成 \(x\) 轴上若干段区间
然后就是区间覆盖的板子了

点击查看代码
#include <bits/stdc++.h>
using namespace std;

const int N = 1e3 + 0721;
int x[N], y[N];
struct node {
    double l, r;
} a[N];
int n, d, ans = 1;

void cl(int id) {
    double dis = sqrt(d * d - y[id] * y[id]);
    a[id].l = x[id] - dis;
    a[id].r = x[id] + dis;
}

bool cmp(node x1, node x2) { return x1.r < x2.r; }

int main() {
    scanf("%d%d", &n, &d);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &x[i], &y[i]);
        if (y[i] > d) {
            printf("-1");
            return 0;
        }
        cl(i);
    }

    sort(a + 1, a + 1 + n, cmp);

    double last = a[1].r;
    for (int i = 2; i <= n; ++i) {
        if (a[i].l <= last && a[i].r >= last)
            continue;
        else
            ++ans, last = a[i].r;
    }

    printf("%d", ans);

    return 0;
}

C.畜栏预定

image
image

一道很友善的贪心题
很容易想到先把牛按 \(l\) 排序 然后把畜栏按结束时间排序
每次取出结束最早的畜栏 并与当前的牛比较
如果在这头牛吃草之前畜栏就空出来 就把这头牛安排到这个畜栏
否则 就需要新加一个畜栏
证明:假如我们不是把牛放到结束时间最早的畜栏
由于牛吃草结束的时间不变 这个畜栏结束的时间不变
对于开始时间 这个畜栏更容易出现忙不过来的情况 就可能出现多的畜栏
所以选结束最早的畜栏一定不会更劣

点击查看代码
#include <bits/stdc++.h>
using namespace std;

const int N = 5e4 + 0721;
struct cow {
    int l, r, id;
} a[N];
int n, cnt, ans[N];

bool cmp(cow x1, cow x2) { return x1.l < x2.l; }

struct node {
    int id, now;
    friend bool operator<(node x1, node x2) { return x1.now > x2.now; }
};
priority_queue<node> q;

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d%d", &a[i].l, &a[i].r), a[i].id = i;

    sort(a + 1, a + 1 + n, cmp);
    cnt = 1, ans[1] = 1, q.push((node){ cnt, a[1].r });
    for (int i = 2; i <= n; ++i) {
        int prs = q.top().id;
        int last = q.top().now;
        //		cout<<a[i].l<<" "<<prs<<" "<<last<<" " ;
        if (a[i].l > last) {
            q.pop();
            ans[a[i].id] = prs;
            last = a[i].r;
            q.push((node){ prs, last });
        } else {
            ++cnt;
            ans[a[i].id] = cnt;
            q.push((node){ cnt, a[i].r });
        }
        //		cout<<ans[i]<<endl;
    }

    printf("%d\n", cnt);
    for (int i = 1; i <= n; ++i) printf("%d\n", ans[i]);

    return 0;
}

D.荷马史诗

image
image
image
image

哈夫曼堆 经典例题可以看P1090 [NOIP2004 提高组] 合并果子
其实就是一个除了最后一层以外满叉的多叉树
我们给每个叉赋予一个编码
那么显然层数越浅的 其编码越短
所以我们要让出现次数多的尽可能的放在上层
所以我们每次把 \(k\) 个最小的元素合并起来 然后丢回堆里 重复此过程
但是要注意一个问题 就是有可能在第一层出现总堆数不够 \(k\) 个的情况 那就没法把这层占满 显然是血亏的 所以我们要另外加一些空点
因为每次合并少了 \(k - 1\) 个果子 一共要把 \(n\) 个果子合并起来所以少了一共 \(n - 1\) 只有当 \(n - 1\)\(k - 1\) 的整数倍时 才能使每次合并都时满 \(k\) 的合并

点击查看代码
#include <bits/stdc++.h>
#define ll long long

using namespace std;

struct node {
	ll val, dep;
	friend bool operator<(node x, node y) {
		if (x.val != y.val)
			return x.val > y.val;
		else
			return x.dep > y.dep;
	}
};
priority_queue<node> q;

int main() {
	int n, k;
	scanf("%d%d", &n, &k);
	for (int i = 1; i <= n; ++i) {
		ll w;
		scanf("%lld", &w);
		q.push((node){ w, 0 });
	}
	
	while ((q.size() - 1) % (k - 1) != 0) {
		q.push((node){ 0, 0 });
	}
	
	ll ans = 0;
	while (q.size() > 1) {
		ll hi = 0;
		ll sum = 0;
		for (int i = 1; i <= k; ++i) {
			sum += q.top().val;
			hi = max(hi, q.top().dep);
			q.pop();
		}
		ans += sum;
		q.push((node){ sum, hi + 1 });
	}
	
	printf("%lld\n%lld",ans,q.top().dep);
	
	return 0;
}
posted @ 2023-06-28 08:41  Steven24  阅读(40)  评论(0编辑  收藏  举报