题解:P2088 果汁店的难题

题目链接 

https://www.luogu.com.cn/problem/P2088

题目描述

炎热的夏天,来上一杯现榨的冰爽果汁想想都是一件惬意的事情!话说小王就看准了这一商机,在学校附近开了这么一家果汁店,但是最近他碰到了一个不大不小的难题:小王的果汁店里准备了 K 台榨汁机,当然每台榨汁机只能榨一种果汁,在某个时段内,一个客人点了某种果汁,如果恰好有某台果汁机榨过这种果汁,那么就直接给客人用这台果汁机接着榨就可以了,但是如果点的是一种新的果汁就需要找一台干净的果汁机来用,问题就出在这,如果这时候还有空的果汁机还好,如果没有的话小王就需要将某台刚才用过的拿去清洗,清洗的话呢就得浪费很多的时间和很多的水,小王是个很有经济头脑的人,他想知道在排队客人需求已知的情况下最少需要清洗多少次果汁机?假定开始时所有果汁机都是干净的,为了方便描述,我们将果汁编号为 1(橙汁), 2(苹果汁), 3 (葡萄汁)......

[友情提示:本店不售卖混合果汁]

输入格式

每组测试数据第一行包括两个整数K,N,其中,K 表示小王准备了 K台干净的榨汁机,N表示排队等待的有 N 个客人,接下来 N 行,每行一个整数表示一个客人点的果汁种类 Xi​ 。

输出格式

输出在当前的请求序列下,小王最少需要清洗果汁机的次数。

解析

通过这段题的描述容易看出这是一道贪心题目。

依据此题有固定的购买顺序,所以对于所遍历到的果汁若没有榨汁机对应,则对于后面出现的每一种果汁出现的第一个位置离该果汁越远所被替换的优先级越高,因为暂时用不到这一种果汁。若后方有一种果汁的个数被清零则将这个果汁到当前位置的距离变为无限远,即优先级最高。 若有对应的榨汁机则直接清洗就好了。

下面提供完整代码。

Code

#include <bits/stdc++.h>
using namespace std;
struct node1
{
	int id=0,shu=0,di=0;
};
//id代表果汁的种类,shu代表果汁的数量,di代表这种果汁距离当前位置的距离。
struct node
{
	node1 a[101];
}b[101];
int c[101];// c数组存储果汁顺序。
int cmp(node1 x,node1 y)
{
	return x.di>y.di;
}
//按照距离排序
int f[101];
int main()
{
	int K,N,maxn=-0x7f7f7f7f,sum=0,ans=0;
	scanf("%d%d",&K,&N);
	for(int i=1;i<=N;i++)
	{
		scanf("%d",&c[i]);
		maxn=max(maxn,c[i]);
	}
  //maxn记录当前数据中果汁的种类量。
	for(int i=N;i>=1;i--)
	{
		for(int j=1;j<=maxn;j++)
		{
			b[i].a[j].shu=b[i+1].a[j].shu;
			b[i].a[j].di=b[i+1].a[j].di;
			if(b[i].a[j].shu==0)
			{
				b[i+1].a[j].di=0x7f7f7f7f;
			}
			b[i].a[j].id=j;
		}
		b[i].a[c[i]].shu=b[i+1].a[c[i]].shu+1;
		b[i].a[c[i]].di=i;
	}//对数据进行初始化。
	for(int i=1;i<=N;i++)
	{
		sort(b[i].a+1,b[i].a+1+maxn,cmp);
	}//将果汁的优先级排序。
	for(int i=1;i<=N;i++)
	{
		if(sum<K&&f[c[i]]==0)//若无对应的榨汁机且有空榨汁机则直接使用。
		{
			sum++;
			f[c[i]]=1;
		}
		else if(f[c[i]]!=1)//否则没有对应榨汁机且无空榨汁机,则将一种果汁存在于当前的榨汁机中,且距离当前位置最远的替换掉。
		{
			ans++;
			for(int j=1;j<=maxn;j++)
			{
				if(f[b[i].a[j].id]==1&&b[i].a[j].id!=c[i])
				{
					f[b[i].a[j].id]=0;
					f[c[i]]=1;
					break;
				}
			}
		}
	}
	printf("%d",ans);
	return 0;
}

如有题目侵权,请联系删除。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值