【Ybt OJ】[基础算法 第2章]贪心算法

「 「 基础算法 」 」 2 2 2章 贪心算法
目录:

A.奶牛晒衣服
B.雷达装置
C.畜栏预定
D.国王游戏

A . A. A. 例题 1 1 1 奶牛晒衣服

洛谷 l i n k link link
在这里插入图片描述

分析:

干衣所需时间是取决于最后一件烘干的衣物的所需时间
所以我们每次对剩余时间最多的衣物用烘干机
对于剩余时间最多 我们可以用一个大根堆维护 s o r t sort sort会超时

CODE:

#include<cstdio>
#include<iostream>
#include<algorithm> 
#include<cstring>
#include<queue>
#define reg register
using namespace std;
priority_queue<int> f;  //大根堆
int n,a,b,x,t; 
int main()
{
    
    
	scanf("%d%d%d",&n,&a,&b);
	for(int i=1;i<=n;i++)
	{
    
    
		scanf("%d",&x);
		f.push(x);
	}
	t+=a;  //单独处理第一天
	int k=f.top();
	f.pop();
	k-=b;
	f.push(k);
	while(1)
	{
    
    
		int k=f.top();
		f.pop();
		if(k-t<=0){
    
    
			printf("%d",t/a);  //总量/单价=数量
			return 0;
		}
		k-=b;  //继续贪心
		f.push(k);
		t+=a;
	}
	return 0;
}  

B . B. B. 例题 2 2 2 雷达装置

洛谷 l i n k link link
在这里插入图片描述

分析:

如果小岛能被探测 则用结构体记录可探测第 i i i个小岛的雷达中 x x x最小值 ( l ) (l) (l)最大值 ( r ) (r) (r) 即区
并将区间数组 r r r排序 这样可以按 x x x小往大遍历
当雷达不够了 则需添加雷达 并重新赋值
注意用勾股定理求距离 最 x − d i s x-dis xdis x + d i s x+dis x+dis

CODE:

#include<cstdio>
#include<iostream>
#include<algorithm> 
#include<cstring>
#include<queue>
#include<cmath>
#define reg register
using namespace std;
int n,d,ans=1;
struct node{
    
    
	double l,r;
}a[1005];
bool cmp(node x,node y){
    
    return x.r<y.r;}
int main()
{
    
    
	scanf("%d%d",&n,&d);
	for(int i=1;i<=n;i++)
	{
    
    
		int x,y;
		scanf("%d%d",&x,&y);
		if(d<y){
    
    
			printf("-1");
			return 0;
		}
		int dis=sqrt(d*d-y*y);  //求距离
		a[i].l=x-dis;a[i].r=x+dis;  //求区间
	}
	sort(a+1,a+n+1,cmp);
	int x=a[1].r;
	for(int i=2;i<=n;i++)
		if(x<a[i].l) x=a[i].r,ans++;  //雷达不够就添加 赋值
	printf("%d",ans);
	return 0;
}  

C . C. C. 例题 3 3 3 畜栏预定

洛谷 l i n k link link
在这里插入图片描述

分析:

贪心策略:

将牛的左端点右端点 分别开结构体存储 再将它们排序
如果牛棚的右端点没有牛棚 就添加一个
然后找后面左端点第一个比该右端点的 放上与该右端点牛相同的牛棚
顺带更新一下 a n s ans ans即可.

CODE:

#include<cstdio>
#include<iostream>
#include<algorithm> 
#include<cstring>
#include<queue>
#include<cmath>
#define reg register
using namespace std;
const int N=5e5+5;
int n,num,ans[N];
struct node{
    
    
	int val,id;
}a[N],b[N];
bool cmp(node x,node y){
    
    return x.val<y.val;}
int main()
{
    
    
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
    
    
		scanf("%d%d",&a[i].val,&b[i].val);
		a[i].id=b[i].id=i; 
	}
	sort(a+1,a+n+1,cmp);
	sort(b+1,b+n+1,cmp);
	for(int i=1,j=1;i<=n;i++)
	{
    
    
		if(j<=n) j++;
		if(!ans[b[i].id]) ans[b[i].id]=++num;  //放新牛棚
		while(a[j].val<=b[i].val&&j<=n) j++;  //向后枚举
		ans[a[j].id]=ans[b[i].id];  //更新答案
	}
	printf("%d\n",num);
	for(int i=1;i<=n;i++)
		printf("%d\n",ans[i]);
	
	return 0;
}  

D . D. D. 例题 4 4 4 国王游戏

洛谷 l i n k link link
在这里插入图片描述

分析:

考虑交换相邻两个人

交换前:

那么 第 i i i位的权值就是 : ( ! a i − 1 ) / b i :(!a_{i-1})/b_i (!ai1)/bi ( ! (! (!阶乘 ) ) )
i + 1 i+1 i+1位的权值同理 : ( ! a i ) / b i + 1 :(!a_i)/b_{i+1} (!ai)/bi+1
其中的最大值 m a x 1 = m a x ( ( ! a i − 1 ) / b i , ( ! a i ) / b i + 1 ) max1=max((!a_{i-1})/b_i,(!a_i)/b_{i+1}) max1=max((!ai1)/bi,(!ai)/bi+1)

交换后

i + 1 i+1 i+1位的权值变为 : ( ! a i − 1 ) / b i + 1 :(!a_{i-1})/b_{i+1} (!ai1)/bi+1
i i i权值变为 : ( ! a i − 1 ) ∗ a i + 1 / b i :(!a_{i-1})*a_{i+1}/b_i (!ai1)ai+1/bi
最大值 m a x 2 = m a x ( ( ! a i − 1 ) / b i + 1 , ( ! a i − 1 ) ∗ a i + 1 / b i ) max2=max((!a_{i-1})/b_{i+1},(!a_{i-1})*a_{i+1}/b_i) max2=max((!ai1)/bi+1,(!ai1)ai+1/bi)
对比一下 ( ! a i − 1 ) / b i (!a_{i-1})/b_i (!ai1)/bi肯定是小于 ( ! a i − 1 ) ∗ a i + 1 / b i (!a_{i-1})*a_{i+1}/b_i (!ai1)ai+1/bi的 如果 m a x 1 < m a x 2 max1<max2 max1<max2说明
( ! a i ) / b i + 1 < ( ! a i − 1 ) ∗ a i + 1 / b i (!a_i)/b_{i+1}<(!a_{i-1})*a_{i+1}/b_i (!ai)/bi+1<(!ai1)ai+1/bi
化简可得: a i ∗ b i < a i + 1 ∗ b i + 1 a_i*b_i<a_{i+1}*b_{i+1} aibi<ai+1bi+1
注意高精

CODE:

#include<cstdio>
#include<iostream>
#include<algorithm> 
#include<cstring>
#include<queue>
#include<cmath>
#define reg register
using namespace std;
const int N=10005;
typedef long long ll;
int n,now[N],ans[N],minn[N],ansn,nown,minx;
struct node{
    
    
	int l,r,lr;  //左手,右手,左右手乘积
}a[N];
bool cmp(node x,node y){
    
    return x.lr<y.lr;}
void Pai(int x)  //累乘函数 高精
{
    
    
	for(reg int i=1;i<=nown;i++)
		now[i]*=x;
	for(reg int i=1;i<=nown;i++)
	{
    
    
		now[i+1]+=now[i]/10;
		now[i]%=10;
		if(i==nown&&now[i+1]!=0) nown++;
	}
}
void dev(int x)  //高精除
{
    
    
	memset(minn,0,sizeof(minn));
	minx=0;
	int val=0;
	for(reg int i=nown;i>0;i--)
	{
    
    
		val=val*10+now[i];
		minn[i]=val/x;
		if(minx==0&&minn[i]!=0) minx=i;
		val%=x;
	}
	for(reg int i=1;i<=minx;i++)
	{
    
    
		minn[i+1]+=minn[i]/10;
		minn[i]%=10;
		if(i==minx&&minn[i+1]!=0) minx++;
	}
}
bool check()
{
    
    
	if(ansn<minx) return true;
	if(minx<ansn) return false;
	for(reg int i=ansn;i>0;i--)
	{
    
    
		if(minn[i]>ans[i]) return true;
		if(minn[i]<ans[i]) return false;
	} 
	return false;
}
void swp(){
    
    
	for(int i=1;i<=minx;i++)
		ans[i]=minn[i];
	ansn=minx;
}
int main()
{
    
    
	scanf("%d",&n);
	for(reg int i=0;i<=n;i++)
	{
    
    
		scanf("%d%d",&a[i].l,&a[i].r);
		a[i].lr=a[i].l*a[i].r;
	}
	sort(a+1,a+n+1,cmp);
	nown=1;now[1]=1;
	for(reg int i=1;i<=n;i++)
	{
    
    
		Pai(a[i-1].l);
		dev(a[i].r);  //贪心策略
		if(check()) swp();
	}
	for(int i=ansn;i>0;i--)
		printf("%d",ans[i]);
	
	return 0;
}  

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/111757408