在写代码的时候碰到了,思考了一下想到了两种方案,有其他思路可以评论或私信 ,谢谢<_>
题目
问题描述:
洗完衣服后,你就要弄干衣服。衣服在自然条件下用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;
}