4月14日

poj1862

题意:把一堆数两两合并为2*sqrt(m1*m2),求最终的最小值

分析:类似哈夫曼树,不过这次要先将大的合并,用一个优先队列维护即可,优先队列默认就是从大到小,即大顶堆

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <vector>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <bitset>
10 #include <cmath>
11 #include <queue>
12 #include <stack>
13 using namespace std;
14 int n;
15 int main()
16 {
17     while(cin>>n)
18     {
19         priority_queue<double>que; //优先队列默认从大到小的顺序
20         for(int i=0;i<n;i++)
21         {
22             double x;
23             cin>>x;
24             que.push(x);
25         }
26         double t1,t2,t;
27         while(que.size()!=1)
28         {
29             t1=que.top();
30             que.pop();
31             t2=que.top();
32             que.pop();
33             t=2*sqrt(t1*t2);
34             que.push(t);
35         }
36         printf("%.3lf
",que.top());
37     }
38     return 0;
39 }
View Code

 poj3262

题意:有n头牛,每头牛都有运输出去所需时间以及每分钟破坏的草的数量,每次运牛i出去需要时间2*ti,这时其他牛在继续破坏草,问怎么才会使破坏的草的数量最小

分析:拿着题的第一思路,按照牛破坏草的数量排序,然后贪心,结果wa了,后来看了题解才知道。我们可以这样进行贪心:

对任意一头牛,例如:
2   7
可以看成两头 1 3.5的牛
也就是说任意一头牛都可以拆成T头
1   D/T
的牛
所以说,所有的牛就都变成了
1    X
按照应该就X从大到小排序,最后用优先队列搞定
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <vector>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <bitset>
10 #include <cmath>
11 #include <queue>
12 #include <stack>
13 using namespace std;
14 const int maxn=100100;
15 typedef struct p
16 {
17     int t,d;
18     double num;
19     friend bool operator<(p a,p b)
20     {
21         return a.num<b.num;  //大顶堆
22     }
23 }p;
24 int main()
25 {
26     int n;
27     while(cin>>n)
28     {
29         priority_queue<p> que;
30         long long sum=0;
31         for(int i=0;i<n;i++)
32         {
33             p s;
34             scanf("%d%d",&s.t,&s.d);
35             sum+=s.d;
36             s.num=(double)s.d/(double)s.t;
37             que.push(s);
38         }
39         long long cnt=0;
40         while(!que.empty())
41         {
42             p h=que.top();
43             que.pop();
44             sum-=h.d;
45             cnt+=2*sum*h.t;
46         }
47         cout<<cnt<<endl;
48     }
49     return 0;
50 }
View Code

51nod 1163

题意:给出某件工作的最晚结束时间和完成这项工作所得得报酬,问如何选择才会获得最大报酬

分析:非常好的贪心题目。首先我们按照最晚结束时间进行排序,然后我们建立一个小跟堆。len表示小跟堆的元素个数。若len<s[i].t,则把当前元素加入堆中;若len=s[i].t,则判断优先队列的队首元素是否小于当前s[i].e,若小于,队首出队,再把s[i].e入队,最后对小跟堆中所有元素进行求和即可

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <vector>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <bitset>
10 #include <cmath>
11 #include <queue>
12 #include <stack>
13 using namespace std;
14 const int maxn=50500;
15 typedef struct p
16 {
17     int e,w;
18 }p;
19 p s[maxn];
20 bool cmp(p a,p b)
21 {
22     return a.e<b.e;
23 }
24 int main()
25 {
26     int n;
27     while(cin>>n)
28     {
29         for(int i=0;i<n;i++)
30             cin>>s[i].e>>s[i].w;
31         sort(s,s+n,cmp);
32         priority_queue<int,vector<int>,greater<int> > que;
33         for(int i=0;i<n;i++)
34         {
35             if(s[i].e>que.size())
36             {
37                 que.push(s[i].w);
38             }else if(s[i].e==que.size())
39             {
40                 int t=que.top();
41                 if(t<s[i].w)
42                 {
43                     que.pop();
44                     que.push(s[i].w);
45                 }
46             }
47         }
48         long long sum=0;
49         while(!que.empty())
50         {
51             sum+=que.top();
52             que.pop();
53         }
54         cout<<sum<<endl;
55     }
56     return 0;
57 }
View Code
原文地址:https://www.cnblogs.com/wolf940509/p/5393393.html