贪心问题

T1:奶牛晒衣服

就湿度大的优先烘干

emmm写他的时候突然想起来学长带着做题时有一个什么产工件的题,其中有一个题解用洗衣机和烘干机模拟 A B 工程。那时候我以为作者大抵是闲的,现在看到此题才明白过来

另外复习一下优先队列

priority_queue<int> a;//默认小根(大顶)
priority_queue<int, vector<int>, less<int> > a;   //同上
priority_queue<int, vector<int>, greater<int> > c;//这样就是大根(小顶)
查看代码
#include<bits/stdc++.h>
using namespace std;
int n,a,b;
priority_queue<int> c;
int main()
{
    scanf("%d%d%d",&n,&a,&b);
    for(int i=0,j;i<n;i++)
    {
        scanf("%d",&j);
        c.push(j);
    }
    int t=0;
    while(c.top()>a*t)
    {
        int now=c.top();
        c.pop();
        t++;
        c.push(now-b);
    }
    printf("%d\n",t);
    return 0;
}

 T2:雷达装置

精度尽量高,其次尽早特判(真水)

查看代码
#include<bits/stdc++.h>
using namespace std;
int n,ans=0;
double d,x[10002],y[10002],temp;
struct node{
	double l,r;
}a[10002];
double cmp(node w,node e){
	return w.r<e.r;
}
int main(){
	cin>>n>>d;
	for(int i=1;i<=n;i++){
		cin>>x[i]>>y[i];
		if(y[i]>d){
			cout<<"-1"<<endl;
			return 0;
		}
		a[i].l=x[i]-sqrt(d*d-y[i]*y[i]);
		a[i].r=x[i]+sqrt(d*d-y[i]*y[i]);
	}
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++){
		if(i==1) temp=a[i].r,ans++;
		else if(temp>a[i].l) continue;
		else temp=a[i].r,ans++;
	}
	cout<<ans<<endl;
	return 0;
}

T3:畜栏预定

经典区间之间的贪心,参考桶排序的想法

查看代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,ans[600000],num;
struct node
{
	int s,p;
}a[100001],b[100001];
int cmp(node x,node y)
{
	return x.s<y.s;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i].s,&b[i].s);
		a[i].p=b[i].p=i;
	}
	sort(a+1,a+n+1,cmp);
	sort(b+1,b+n+1,cmp);
	int j=1;
	for(int i=1;i<=n;i++)
	{
		if(j<=n)j++;
		if(!ans[b[i].p])ans[b[i].p]=++num;
		while(a[j].s<=b[i].s&&j<=n)j++;
		ans[a[j].p]=ans[b[i].p];
	}
	printf("%d\n",num);
	for(int i=1;i<=n;i++)
	{
		printf("%d\n",ans[i]);
	}
	return 0;
}

T4:荷马史诗

看人家的小日子过的。。。

很zz的 k 进制串有一个高大上的名字叫做多叉哈夫曼树。

       k 叉树存数方式恰好符合 k 进制串。为了保证某个串不是另一个串的前缀,我们只需要保证某一个串的结尾是这一个树的叶节点即可。我们发现 长度 * 出现次数=到根节点的距离 * 这一个点的点权,这正好对应了一个 Huffman 问题。我们只要保证这一个乘积之和最小,然后我们再考虑如何用 Haffman 树来搞。对于 k 叉 Huffman 树的构造,如果 k = 2 我们就可以采用贪心的策略:

  • 每一次选取最小的两个,累计答案,相加后放入堆中。
  • 最后这一个相加的值就是最后 Huffman 数的答案,即 Huffman 树每一个叶节点到跟节点的距离和 或 非叶节点的点权和。

        然后对于 k>2 的情况,如果按照上面的方法合并,如果在最后一次合并时节点不足 k 个,则随便把最底下的拿上来都可以时结果更优。因此通过思考,我们发现当 ( n − 1 )   m o d   ( k − 1 ) = 0 使是一棵满满当当的 Huffman 数, n 时节点数,即除了最底层有 k 个之外每一层都只有 k − 1 个,同时总叶节点数也除去特殊的哪一个,那么当只一个条件满足后就没有多余的位子可以插入。如果不行,就在后面补权值为 0 的叶节点直到满足这一个条件。

查看代码

#include<bits/stdc++.h>
#define LL long long
using namespace std;
struct node {
	LL x,v;
	bool operator < (const node &aa) const {
		return x>aa.x || (x==aa.x && v>aa.v);
	}
};
priority_queue<node> q;
int n,m;
int main() {
	LL x;
	scanf("%d%d",&n,&m);
	for (int i=1; i<=n; i++) {
		scanf("%lld",&x);
		q.push((node) {
			x,0
		});
	}
	while ((n-1)%(m-1)!=0) {
		++n;
		q.push((node) {
			0LL,0
		});
	}
	LL ans=0;
	while (q.size()>1) {
		LL sum=0,d=0;
		for (int i=1; i<=m; i++)
			if (!q.empty()) {
				node now=q.top();
				q.pop();
				sum+=now.x;
				if (now.v>d) d=now.v;
			}
		ans+=sum;
		q.push((node) {
			sum,++d
		});
	}
	cout<<ans<<endl<<q.top().v;
	return 0;
}
posted @ 2022-02-17 20:52  fervency  阅读(14)  评论(0编辑  收藏  举报