考察:贪心
这道题的贪心好难理解....在网上也没看到证明...
思路:
首先是洗衣服的时间,这时所有衣服的开始时间相同.用优先队列存储每个洗衣机,每件衣服都用耗时最少的,如果该洗衣机被选过一次,那么就相当于有一台t*2的洗衣机.由此算出每件衣服洗完的时间.
然后是烘干的时间.看了很多题解基本默认最后一件衣服放在最快的烘干机里能得到最优解.
我是这么理解的: wash[1...i]按顺序在数轴上,最后的答案是右边界.如果要让答案尽可能小,那么右边界也要尽可能小.最后一件能贡献的最小答案是wash+h1(最小烘干时间).但是答案不一定是这个.因为前面的衣服可能贡献更大的右边界.如倒数第二件,它可能是用h1或h2的烘干机.如果用h1,那么贡献的右边界是wash[i-1]+h1*2,如果用h2,那么右边界是wash[i-1]+h2(此时与wash[i-1]+h1比较看哪个大).以此类推前面的衣服.前面的衣服会受后面衣服选择的影响,取max是因为wash[i]可能不是正确的开始点.wash[i-1]+h1可能比wash[i]大,取max算到正确的右边界.
这里还有篇博客给出了解释,本蒟蒻还是不能理解 GO
除此之外,网上还有用二分的做法,时间比优先队列快很多.
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #include <queue> 6 using namespace std; 7 typedef long long ll; 8 typedef pair<ll,ll> PII; 9 const int N = 1000010; 10 PII p[N/10]; 11 ll wash[N];//wash数组表示洗完第i件衣服的时间 12 int main()//从贪心角度考虑,要让时间最少,就要让最晚洗完的最快烘干 13 { 14 int T,kcase = 0; 15 scanf("%d",&T); 16 while(T--) 17 { 18 int L,n,m; 19 ll ans = 0; 20 scanf("%d%d%d",&L,&n,&m); 21 priority_queue<PII,vector<PII>,greater<PII> >q; 22 for(int i=1;i<=n;i++) 23 { 24 ll x; 25 scanf("%lld",&x); 26 q.push({x,x}); 27 } 28 for(int i=1;i<=L;i++) 29 { 30 PII p = q.top(); q.pop(); 31 wash[i] = p.first; 32 p.first+=p.second; 33 q.push(p); 34 } 35 while(!q.empty()) q.pop(); 36 for(int i=1;i<=m;i++) 37 { 38 ll x; scanf("%lld",&x); 39 q.push({x,x}); 40 } 41 for(int i=L;i>0;i--) 42 { 43 PII p = q.top(); q.pop(); 44 ans = max(p.first+wash[i],ans); 45 p.first+=p.second; 46 q.push(p); 47 } 48 printf("Case #%d: %lld\n",++kcase, ans); 49 } 50 return 0; 51 }打死我也想不到的贪心