Wash HDU - 6000

原题链接

考察:贪心

这道题的贪心好难理解....在网上也没看到证明...

思路:

        首先是洗衣服的时间,这时所有衣服的开始时间相同.用优先队列存储每个洗衣机,每件衣服都用耗时最少的,如果该洗衣机被选过一次,那么就相当于有一台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算到正确的右边界.

这里还有篇博客的代码和解释好理解点,dry数组表示第i件衣服烘干所需要的时间.为了让答案最小,我们需要让第一件衣服尽可能慢地烘干.相当于将起点往后移到wash[i]处. 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],dry[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=1;i<=L;i++)
42         {
43             PII x = q.top(); q.pop();
44             dry[i] = x.first;
45             x.first+=x.second;
46             q.push(x);
47         }
48         for(int i=1;i<=L;i++) ans = max(ans,wash[i]+dry[L-i+1]);
49         printf("Case #%d: %lld\n",++kcase, ans);
50     }
51     return 0;
52 }
dry数组的做法
 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 }
完全不能理解的做法

 

posted @ 2021-02-21 17:56  acmloser  阅读(57)  评论(0编辑  收藏  举报