Poj--3253(贪心 / 优先队列)

2014-11-30 19:42:25

思路:思考得最优解肯定是越长的越早分离出来,越短的越后分出来(即:最短的算的次数最多),那么我们可以倒过来考虑,从集合中把最短的两根取出,合并,再加入集合,中间累加...一直到集合中就剩下一个元素停止。可以直接暴力贪心O(n*n),优先队列是O(nlog(n))

(1)贪心(个人感觉这个贪心的姿势挺优美,参考自巫大叔)

 1 /*************************************************************************
 2     > File Name: 3253.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Sun 30 Nov 2014 06:37:40 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int N,L[20010],min1,min2;
28 ll ans;
29 
30 int main(){
31     while(scanf("%d",&N) != EOF){
32         min1 = min2 = INF;
33         for(int i = 1; i <= N; ++i){
34             scanf("%d",L + i);
35         }
36         ans = 0;
37         while(N > 1){
38             min1 = 1;
39             min2 = 2;
40             if(L[min1] > L[min2]) swap(min1,min2);
41             for(int i = 3; i <= N; ++i){
42                 if(L[i] < L[min1]){
43                     min2 = min1;
44                     min1 = i;
45                 }
46                 else if(L[i] < L[min2]){
47                     min2 = i;
48                 }
49             }
50             int t = L[min1] + L[min2];
51             ans += t;
52             if(min1 == N) swap(min1,min2);
53             L[min1] = t;
54             L[min2] = L[N--];
55         }
56         printf("%I64d\n",ans);
57     }
58     return 0;
59 }
View Code

(2)优先队列

 1 /*************************************************************************
 2     > File Name: 3253_2.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Sun 30 Nov 2014 07:12:55 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int N,v;
28 ll ans;
29 
30 int main(){
31     while(scanf("%d",&N) != EOF){
32         priority_queue<int,vector<int>,greater<int> > Q;
33         for(int i = 1; i <= N; ++i){
34             scanf("%d",&v);
35             Q.push(v);
36         }
37         ans = 0;
38         int min1,min2;
39         while(1){
40             min1 = Q.top(); Q.pop();
41             if(Q.empty()){
42                 break;
43             }
44             min2 = Q.top(); Q.pop();
45             ans += min1 + min2;
46             Q.push(min1 + min2);
47         }
48         printf("%I64d\n",ans);
49     }
50     return 0;
51 }

 

转载于:https://www.cnblogs.com/naturepengchen/articles/4133560.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值