奶牛晒衣服C++代码实现 超详解版本(实至名归)

在写代码的时候碰到了,思考了一下想到了两种方案,有其他思路可以评论或私信 ,谢谢<_>

题目

问题描述:
洗完衣服后,你就要弄干衣服。衣服在自然条件下用1个单位的时间可以晒干A点湿度。现在买了1台烘衣机,使用烘衣机可以让你用1个单位的时间使1件衣服除开自然晒干的A点湿度外,还可烘干B点湿度,但在1个单位的时间内只能对1件衣服使用。 N件衣服因为种种原因而不一样湿,现在告诉你每件衣服的湿度,要你求出弄干所有衣服的最少时间(湿度为0为干)。

输入格式:
第一行N,A,B; 接下来N行,每行一个数,表示衣服的湿度(1<=湿度,A,B<=500000,1<=N<=500000)。

输出格式:
一行一个整数,表示最少时间。

Sample Input 1
3 2 1
1
2
3
Sample Output 1
1
样例解析:
第1个单位时间内,用机器处理第3件衣服,此外,所有衣服自然晒干2。

思路解析

本人更倾向于用贪心,即优先队列解决,因为快

方法一:二分答案

设wet[i]为第i件衣服的湿度,当前答案范围是[L,R]。(一开始答案范围是[1,500000])

先二分一个答案ans,然后枚举每件衣服,若wet[i]<=ansA,则表示第i件衣服可以自然晒干,否则表示需要用(wet[i]-ansA)/B(取上整)个单位时间的烘衣机,我们用time累计烘衣机所用的时间。

若最后time<=ans,则表示该答案可行,更新答案,并继续在[L,ans-1]内进行二分答案。

若最后time>ans,则表示该答案不行,继续在[ans+1,R]内进行二分答案。

直到L>R停止。

方法二:贪心

利用贪心的策略模拟整个烘衣过程。对于每个时刻,我们显然用烘衣机去处理湿度最大的衣服会使得答案更优。

设k表示当前所有衣服的湿度减少了多少,a[i]表示在烘干机作用下当前湿度为i的衣服有多少件,max表示在烘干机作用下湿度最大的衣服的湿度。

那么每个时刻我们所有衣服的湿度都需减少A,所以每个时刻k就累计一个A。同时我们的烘干机会对湿度最大的衣服进行烘干,所以a[max]会减少一,表示湿度最大的衣服少了一件了,并且a[max-B]会增加一,表示原来那件湿度最大的衣服烘干后成了湿度为max-B的衣服了。若a[max]=0,则代表湿度最大的衣服没有了,max递减,直到a[max]<>0为止。

当某个时刻max<=k了,就表示我们所有衣服已经烘干了,并且我们得到了一个最小的时间。这个贪心算法的总时间复杂度为(最大湿度+衣服个数)。

代码实现

1.二分答案

//贪心算法

#include <iostream>
#include <cstdio>
#include <algorithm> 
#define LL long long 
 
using namespace std;
int n, a, b, l ,r, sum, mid, maxr;
int w[500005];
 
bool check(int x){
    sum = 0;
    for(int i = 0; i < n; i++){
        int re = w[i] - (x * a);
        if(re > 0)
            sum += re / b + (re % b != 0);
    }
    return sum <= x;
}
 
int main(){
 
    scanf("%d%d%d",&n, &a, &b);
    maxr = -1;
    for(int i = 0; i < n; i++){
        scanf("%d",&w[i]);
        maxr = max(maxr, w[i]);
    }
    l = 1; r = maxr / a;
    while(l < r){
        mid = (l+r) >> 1;
        if(check(mid))
            r = mid;
        else
            l = mid + 1;
        
    }
    while(!check(r)){
        r++;
    }
    printf("%d\n",r); 
    
 
    return 0;
} 

2.贪心算法

这里有两种算法,效率都很高。

主要通过计算来减少优先队列的转化次数,节省时间,使其能够容纳更大的数据,不会超时。

第一种

#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int> > q;
int n,a,b,m,c[1232121],t,p; 
int main(){
	cin>>n>>a>>b;
	for(int i=1;i<=n;i++){
		cin>>c[i];
		q.push(c[i]);
	}
	while(q.top()-t*a>0){
		p=q.top();
		q.pop();
		p=p-b;
		q.push(p);
        t++;
	}
	cout<<t<<endl;
	
	return 0;
}

第二种

#include<bits/stdc++.h>
using namespace std;
priority_queue<int> p;
int n,a,b,k,m=0;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>a>>b;
	for(int i=1;i<=n;i++){
		cin>>k;p.push(k);
	}
	k=0;
	while(!(p.top()<=m)){
		k++;
		p.push(p.top()-b);
		p.pop();
		m+=a;
	}
	cout<<k;
	return 0;
}

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值